diff options
author | unknown <serg@serg.mylan> | 2004-02-13 15:27:21 +0100 |
---|---|---|
committer | unknown <serg@serg.mylan> | 2004-02-13 15:27:21 +0100 |
commit | 98150adcec185a147426a2cea5d7ea582c609fd2 (patch) | |
tree | e72eb3285c6d77bd43ee040603595ce715626551 /strings | |
parent | 5beeb066ad74dbca5d663915bb1b83277a96f5d7 (diff) | |
download | mariadb-git-98150adcec185a147426a2cea5d7ea582c609fd2.tar.gz |
my_atof is deleted
strtod from mit-threads is restored and cleaned up
BitKeeper/deleted/.del-atof.c~d3edf47a9884080:
Delete: strings/atof.c
configure.in:
atod() is no longer used in MySQL
isinf() now is
include/m_string.h:
my_strtod, my_atof
include/my_global.h:
my_atof is deleted
define isinf()
libmysql/Makefile.shared:
use internal strtod
sql/gstream.cc:
use internal strtod
sql/init.cc:
my_atof is deleted
sql/item.h:
use internal strtod
sql/item_func.cc:
use internal strtod
sql/item_sum.h:
use internal strtod
sql/sql_analyse.cc:
use internal strtod
strings/Makefile.am:
use internal strtod
strings/ctype-simple.c:
use internal strtod
strings/ctype-ucs2.c:
use internal strtod
strings/strtod.c:
cleanup
stricter input checks (e.g. ".E10" is no longer a number)
don't return an "inf"
Diffstat (limited to 'strings')
-rw-r--r-- | strings/Makefile.am | 6 | ||||
-rw-r--r-- | strings/atof.c | 207 | ||||
-rw-r--r-- | strings/ctype-simple.c | 6 | ||||
-rw-r--r-- | strings/ctype-ucs2.c | 6 | ||||
-rw-r--r-- | strings/strtod.c | 140 |
5 files changed, 149 insertions, 216 deletions
diff --git a/strings/Makefile.am b/strings/Makefile.am index 61219c8abb9..89f32ac6b40 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -22,19 +22,19 @@ pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X if ASSEMBLER_x86 ASRCS = strings-x86.s longlong2str-x86.s my_strtoll10-x86.s -CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c +CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c else if ASSEMBLER_sparc32 # These file MUST all be on the same line!! Otherwise automake # generats a very broken makefile ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s -CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c +CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c else #no assembler ASRCS = # These file MUST all be on the same line!! Otherwise automake # generats a very broken makefile -CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c +CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c endif endif diff --git a/strings/atof.c b/strings/atof.c deleted file mode 100644 index 0e0aa598718..00000000000 --- a/strings/atof.c +++ /dev/null @@ -1,207 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* - A quicker atof. About 2-10 times faster than standard atof on sparc. - This don't handle iee-options (NaN...) and the presission :s is a little - less for some high exponential numbers (+-1 at 14th place). - Returns 0.0 if overflow or wrong number. - Must be inited with init_my_atof to handle possibly overflows. -*/ - -#include <my_global.h> -#ifdef USE_MY_ATOF /* Skipp if we don't want it */ -#include <m_ctype.h> -#include <floatingpoint.h> -#include <signal.h> - -/* Read a double. If float is wrong return 0. - float ::= [space]* [sign] {digit}+ decimal-point {digit}+ [exponent] | - [sign] {digit}+ [decimal-point {digit}*] exponent | - [sign] {digit}+ decimal-point [{digit}*] exponent | - [sign] decimal-point {digit}* exponent | - exponent :: = exponent-marker [sign] {digit}+ - exponent-marker ::= E e - */ - - -#define is_exponent_marker(ch) (ch == 'E' || ch == 'e') - -static void my_atof_overflow _A((int sig,int code, struct sigcontext *scp, - char *addr)); -static int parse_sign _A((char **str)); -static void parse_float_number_part _A((char **str,double *number, int *length)); -static void parse_decimal_number_part _A((char **str,double *number)); -static int parse_int_number_part _A((char **str,uint *number)); - -static int volatile overflow,in_my_atof; -static sigfpe_handler_type old_overflow_handler; - -void init_my_atof() -{ - old_overflow_handler = (sigfpe_handler_type) - ieee_handler("get", "overflow", old_overflow_handler); - VOID(ieee_handler("set", "overflow", my_atof_overflow)); - return; -} - -static void my_atof_overflow(sig, code, scp, addr) -int sig; -int code; -struct sigcontext *scp; -char *addr; -{ - if (!in_my_atof) - old_overflow_handler(sig,code,scp,addr); - else - overflow=1; - return; -} - -double my_atof(src) -const char *src; -{ - int sign, exp_sign; /* is number negative (+1) or positive (-1) */ - int length_before_point; - double after_point; /* Number after decimal point and before exp */ - uint exponent; /* Exponent value */ - double exp_log,exp_val; - char *tmp_src; - double result_number; - - tmp_src = (char*) src; - while (isspace(tmp_src[0])) - tmp_src++; /* Skipp pre-space */ - sign = parse_sign(&tmp_src); - overflow=0; - in_my_atof=1; - parse_float_number_part(&tmp_src, &result_number, &length_before_point); - if (*tmp_src == '.') - { - tmp_src++; - parse_decimal_number_part(&tmp_src, &after_point); - result_number += after_point; - } - else if (length_before_point == 0) - { - in_my_atof=0; - return 0.0; - } - if (is_exponent_marker(*tmp_src)) - { - tmp_src++; - exp_sign = parse_sign(&tmp_src); - overflow|=parse_int_number_part(&tmp_src, &exponent); - - exp_log=10.0; exp_val=1.0; - for (;;) - { - if (exponent & 1) - { - exp_val*= exp_log; - exponent--; - } - if (!exponent) - break; - exp_log*=exp_log; - exponent>>=1; - } - if (exp_sign < 0) - result_number*=exp_val; - else - result_number/=exp_val; - } - if (sign > 0) - result_number= -result_number; - - in_my_atof=0; - if (overflow) - return 0.0; - return result_number; -} - - -static int parse_sign(str) -char **str; -{ - if (**str == '-') - { - (*str)++; - return 1; - } - if (**str == '+') - (*str)++; - return -1; -} - - /* Get number with may be separated with ',' */ - -static void parse_float_number_part(str, number, length) -char **str; -double *number; -int *length; -{ - *number = 0; - *length = 0; - - for (;;) - { - while (isdigit(**str)) - { - (*length)++; - *number = (*number * 10) + (**str - '0'); - (*str)++; - } - if (**str != ',') - return; /* Skipp possibly ',' */ - (*str)++; - } -} - -static void parse_decimal_number_part(str, number) -char **str; -double *number; -{ - double exp_log; - - *number = 0; - exp_log=1/10.0; - while (isdigit(**str)) - { - *number+= (**str - '0')*exp_log; - exp_log/=10; - (*str)++; - } -} - - /* Parses int suitably for exponent */ - -static int parse_int_number_part(str, number) -char **str; -uint *number; -{ - *number = 0; - while (isdigit(**str)) - { - if (*number >= ((uint) ~0)/10) - return 1; /* Don't overflow */ - *number = (*number * 10) + **str - '0'; - (*str)++; - } - return 0; -} - -#endif diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 6f77d6f3e16..c55d12fcd3c 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -684,7 +684,7 @@ noconv: double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), - char *str, uint length, + char *str, uint length, char **end, int *err) { char end_char; @@ -702,12 +702,12 @@ double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), #else if (length == INT_MAX32 || str[length] == 0) #endif - result= strtod(str, end); + result= my_strtod(str, end); else { end_char= str[length]; str[length]= 0; - result= strtod(str, end); + result= my_strtod(str, end); str[length]= end_char; /* Restore end char */ } *err= errno; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index a7a59fc50f7..94f0a1bb2a2 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -856,7 +856,7 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), if (length >= sizeof(buf)) length= sizeof(buf)-1; end= s+length; - + while ((cnv=cs->cset->mb_wc(cs,&wc,s,end)) > 0) { s+=cnv; @@ -865,9 +865,9 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), *b++= (char) wc; } *b= 0; - + errno= 0; - res=strtod(buf, endptr); + res=my_strtod(buf, endptr); *err= errno; if (endptr) *endptr=(char*) (*endptr-buf+nptr); diff --git a/strings/strtod.c b/strings/strtod.c new file mode 100644 index 00000000000..ea6acbac6c4 --- /dev/null +++ b/strings/strtod.c @@ -0,0 +1,140 @@ +/* + An alternative implementation of "strtod()" that is both + simplier, and thread-safe. + + From mit-threads as bundled with MySQL 3.22 + + SQL:2003 specifies a number as + +<signed numeric literal> ::= [ <sign> ] <unsigned numeric literal> + +<unsigned numeric literal> ::= + <exact numeric literal> + | <approximate numeric literal> + +<exact numeric literal> ::= + <unsigned integer> [ <period> [ <unsigned integer> ] ] + | <period> <unsigned integer> + +<approximate numeric literal> ::= <mantissa> E <exponent> + +<mantissa> ::= <exact numeric literal> + +<exponent> ::= <signed integer> + + So do we. + + */ + +#include "my_base.h" +#include "m_ctype.h" + +static double scaler10[] = { + 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 +}; +static double scaler1[] = { + 1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 +}; + +// let's use a static array for not to accumulate the error +static double pastpoint[] = { + 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, + 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19, + 1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29, + 1e-30, 1e-31, 1e-32, 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38, 1e-39, + 1e-40, 1e-41, 1e-42, 1e-43, 1e-44, 1e-45, 1e-46, 1e-47, 1e-48, 1e-49, + 1e-50, 1e-51, 1e-52, 1e-53, 1e-54, 1e-55, 1e-56, 1e-57, 1e-58, 1e-59, +}; + +double my_strtod(const char *str, char **end) +{ + double result= 0.0; + int negative, ndigits; + const char *old_str; + + while (my_isspace(&my_charset_latin1, *str)) + str++; + + if ((negative= (*str == '-')) || *str=='+') + str++; + + old_str= str; + while (my_isdigit (&my_charset_latin1, *str)) + { + result= result*10.0 + (*str - '0'); + str++; + } + ndigits= str-old_str; + + if (*str == '.') + { + int n= 0; + str++; + old_str= str; + while (my_isdigit (&my_charset_latin1, *str)) + { + if (n < sizeof(pastpoint)/sizeof(pastpoint[0])) + { + result+= pastpoint[n] * (*str - '0'); + n++; + } + str++; + } + ndigits+= str-old_str; + if (!ndigits) str--; + } + if (ndigits && (*str=='e' || *str=='E')) + { + int exp= 0; + int neg= 0; + const char *old_str= str++; + + if ((neg= (*str == '-')) || *str == '+') + str++; + + if (!my_isdigit (&my_charset_latin1, *str)) + str= old_str; + else + { + double scaler= 1.0; + while (my_isdigit (&my_charset_latin1, *str)) + { + exp= exp*10 + *str - '0'; + str++; + } + if (exp >= 1000) + { + if (neg) + result= 0.0; + else + result= DBL_MAX; + goto done; + } + while (exp >= 100) + { + scaler*= 1.0e100; + exp-= 100; + } + scaler*= scaler10[exp/10]*scaler1[exp%10]; + if (neg) + result/= scaler; + else + result*= scaler; + } + } + +done: + if (end) + *end = (char *)str; + + if (isinf(result)) + result=DBL_MAX; + + return negative ? -result : result; +} + +double my_atof(const char *nptr) +{ + return (strtod(nptr, 0)); +} + |