LCOV - code coverage report
Current view: directory - port - cpl_strtod.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 60 43 71.7 %
Date: 2012-04-28 Functions: 8 5 62.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: cpl_strtod.cpp 23937 2012-02-10 20:23:24Z rouault $
       3                 :  *
       4                 :  * Project:  CPL - Common Portability Library
       5                 :  * Purpose:  Functions to convert ASCII string to floating point number.
       6                 :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu.
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2006, Andrey Kiselev
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include <locale.h>
      31                 : #include <errno.h>
      32                 : #include <stdlib.h>
      33                 : 
      34                 : #include "cpl_conv.h"
      35                 : 
      36                 : CPL_CVSID("$Id: cpl_strtod.cpp 23937 2012-02-10 20:23:24Z rouault $");
      37                 : 
      38                 : // XXX: with GCC 2.95 strtof() function is only available when in c99 mode.
      39                 : // Fix it here not touching the compiler options.
      40                 : #if defined(HAVE_STRTOF) && !HAVE_DECL_STRTOF
      41                 : extern "C" {
      42                 : extern float strtof(const char *nptr, char **endptr);
      43                 : }
      44                 : #endif
      45                 : 
      46                 : #ifndef NAN
      47                 : #  ifdef HUGE_VAL
      48                 : #    define NAN (HUGE_VAL * 0.0)
      49                 : #  else
      50                 : 
      51                 : static float CPLNaN(void)
      52                 : {
      53                 :     float fNan;
      54                 :     int nNan = 0x7FC00000;
      55                 :     memcpy(&fNan, &nNan, 4);
      56                 :     return fNan;
      57                 : }
      58                 : 
      59                 : #    define NAN CPLNan()
      60                 : #  endif
      61                 : #endif
      62                 : 
      63                 : #ifndef INFINITY
      64                 :     static CPL_INLINE double CPLInfinity(void)
      65                 :     {
      66                 :         static double ZERO = 0;
      67                 :         return 1.0 / ZERO; /* MSVC doesn't like 1.0 / 0.0 */
      68                 :     }
      69                 :     #define INFINITY CPLInfinity()
      70                 : #endif
      71                 : 
      72                 : /************************************************************************/
      73                 : /*                            CPLAtofDelim()                            */
      74                 : /************************************************************************/
      75                 : 
      76                 : /**
      77                 :  * Converts ASCII string to floating point number.
      78                 :  *
      79                 :  * This function converts the initial portion of the string pointed to
      80                 :  * by nptr to double floating point representation. The behaviour is the
      81                 :  * same as
      82                 :  *
      83                 :  *   CPLStrtodDelim(nptr, (char **)NULL, point);
      84                 :  *
      85                 :  * This function does the same as standard atof(3), but does not take locale
      86                 :  * in account. Instead of locale defined decimal delimiter you can specify
      87                 :  * your own one. Also see notes for CPLAtof() function.
      88                 :  *
      89                 :  * @param nptr Pointer to string to convert.
      90                 :  * @param point Decimal delimiter.
      91                 :  *
      92                 :  * @return Converted value, if any.
      93                 :  */
      94               0 : double CPLAtofDelim(const char *nptr, char point)
      95                 : {
      96               0 :   return CPLStrtodDelim(nptr, 0, point);
      97                 : }
      98                 : 
      99                 : /************************************************************************/
     100                 : /*                              CPLAtof()                               */
     101                 : /************************************************************************/
     102                 : 
     103                 : /**
     104                 :  * Converts ASCII string to floating point number.
     105                 :  *
     106                 :  * This function converts the initial portion of the string pointed to
     107                 :  * by nptr to double floating point representation. The behaviour is the
     108                 :  * same as
     109                 :  *
     110                 :  *   CPLStrtod(nptr, (char **)NULL);
     111                 :  *
     112                 :  * This function does the same as standard atof(3), but does not take
     113                 :  * locale in account. That means, the decimal delimiter is always '.'
     114                 :  * (decimal point). Use CPLAtofDelim() function if you want to specify
     115                 :  * custom delimiter.
     116                 :  *
     117                 :  * IMPORTANT NOTE.
     118                 :  * Existance of this function does not mean you should always use it.
     119                 :  * Sometimes you should use standard locale aware atof(3) and its family. When
     120                 :  * you need to process the user's input (for example, command line parameters)
     121                 :  * use atof(3), because user works in localized environment and her input will
     122                 :  * be done accordingly the locale set. In particular that means we should not
     123                 :  * make assumptions about character used as decimal delimiter, it can be
     124                 :  * either "." or ",".
     125                 :  * But when you are parsing some ASCII file in predefined format, you most
     126                 :  * likely need CPLAtof(), because such files distributed across the systems
     127                 :  * with different locales and floating point representation shoudl be
     128                 :  * considered as a part of file format. If the format uses "." as a delimiter
     129                 :  * the same character must be used when parsing number regardless of actual
     130                 :  * locale setting.
     131                 :  *
     132                 :  * @param nptr Pointer to string to convert.
     133                 :  *
     134                 :  * @return Converted value, if any.
     135                 :  */
     136         2197158 : double CPLAtof(const char *nptr)
     137                 : {
     138         2197158 :   return CPLStrtod(nptr, 0);
     139                 : }
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                              CPLAtofM()                              */
     143                 : /************************************************************************/
     144                 : 
     145                 : /**
     146                 :  * Converts ASCII string to floating point number using any numeric locale.
     147                 :  *
     148                 :  * This function converts the initial portion of the string pointed to
     149                 :  * by nptr to double floating point representation. This function does the
     150                 :  * same as standard atof(), but it allows a variety of locale representations.
     151                 :  * That is it supports numeric values with either a comma or a period for 
     152                 :  * the decimal delimiter. 
     153                 :  * 
     154                 :  * PS. The M stands for Multi-lingual.
     155                 :  *
     156                 :  * @param nptr The string to convert.
     157                 :  *
     158                 :  * @return Converted value, if any.  Zero on failure.
     159                 :  */
     160                 : 
     161          697504 : double CPLAtofM( const char *nptr )
     162                 : 
     163                 : {
     164                 :     int i;
     165                 :     const static int nMaxSearch = 50;
     166                 : 
     167         4280642 :     for( i = 0; i < nMaxSearch; i++ )
     168                 :     {
     169         4280642 :         if( nptr[i] == ',' )
     170             378 :             return CPLStrtodDelim( nptr, 0, ',' );
     171         4280264 :         else if( nptr[i] == '.' || nptr[i] == '\0' )
     172          697126 :             return CPLStrtodDelim( nptr, 0, '.' );
     173                 :     }
     174                 : 
     175               0 :     return CPLStrtodDelim( nptr, 0, '.' );
     176                 : }
     177                 : 
     178                 : /************************************************************************/
     179                 : /*                      CPLReplacePointByLocalePoint()                  */
     180                 : /************************************************************************/
     181                 : 
     182         2914540 : static char* CPLReplacePointByLocalePoint(const char* pszNumber, char point)
     183                 : {
     184                 : #if defined(WIN32CE) || defined(__ANDROID__)
     185                 :     static char byPoint = 0;
     186                 :     if (byPoint == 0)
     187                 :     {
     188                 :         char szBuf[16];
     189                 :         sprintf(szBuf, "%.1f", 1.0);
     190                 :         byPoint = szBuf[1];
     191                 :     }
     192                 :     if (point != byPoint)
     193                 :     {
     194                 :         const char* pszPoint = strchr(pszNumber, point);
     195                 :         if (pszPoint)
     196                 :         {
     197                 :             char* pszNew = CPLStrdup(pszNumber);
     198                 :             pszNew[pszPoint - pszNumber] = byPoint;
     199                 :             return pszNew;
     200                 :         }
     201                 :     }
     202                 : #else
     203         2914540 :     struct lconv *poLconv = localeconv();
     204         2914540 :     if ( poLconv
     205                 :          && poLconv->decimal_point
     206                 :          && strlen(poLconv->decimal_point) > 0 )
     207                 :     {
     208         2914540 :         char    byPoint = poLconv->decimal_point[0];
     209                 : 
     210         2914540 :         if (point != byPoint)
     211                 :         {
     212             378 :             const char* pszPoint = strchr(pszNumber, point);
     213             378 :             if (pszPoint)
     214                 :             {
     215             378 :                 char* pszNew = CPLStrdup(pszNumber);
     216             378 :                 pszNew[pszPoint - pszNumber] = byPoint;
     217             378 :                 return pszNew;
     218                 :             }
     219                 :         }
     220                 :     }
     221                 : #endif
     222         2914162 :     return (char*) pszNumber;
     223                 : }
     224                 : 
     225                 : /************************************************************************/
     226                 : /*                          CPLStrtodDelim()                            */
     227                 : /************************************************************************/
     228                 : 
     229                 : /**
     230                 :  * Converts ASCII string to floating point number using specified delimiter.
     231                 :  *
     232                 :  * This function converts the initial portion of the string pointed to
     233                 :  * by nptr to double floating point representation. This function does the
     234                 :  * same as standard strtod(3), but does not take locale in account. Instead of
     235                 :  * locale defined decimal delimiter you can specify your own one. Also see
     236                 :  * notes for CPLAtof() function.
     237                 :  *
     238                 :  * @param nptr Pointer to string to convert.
     239                 :  * @param endptr If is not NULL, a pointer to the character after the last
     240                 :  * character used in the conversion is stored in the location referenced
     241                 :  * by endptr.
     242                 :  * @param point Decimal delimiter.
     243                 :  *
     244                 :  * @return Converted value, if any.
     245                 :  */
     246         2914586 : double CPLStrtodDelim(const char *nptr, char **endptr, char point)
     247                 : {
     248         2914586 :     if (nptr[0] == '-')
     249                 :     {
     250          127181 :         if (strcmp(nptr, "-1.#QNAN") == 0 ||
     251                 :             strcmp(nptr, "-1.#IND") == 0)
     252               0 :             return NAN;
     253                 : 
     254          127181 :         if (strcmp(nptr,"-inf") == 0 ||
     255                 :             strcmp(nptr,"-1.#INF") == 0)
     256               4 :             return -INFINITY;
     257                 :     }
     258         2787405 :     else if (nptr[0] == '1')
     259                 :     {
     260          538079 :         if (strcmp(nptr, "1.#QNAN") == 0)
     261               0 :             return NAN;
     262          538079 :         if (strcmp (nptr,"1.#INF") == 0)
     263               2 :             return INFINITY;
     264                 :     }
     265         2249326 :     else if (nptr[0] == 'i' && strcmp(nptr,"inf") == 0)
     266               2 :         return INFINITY;
     267         2249324 :     else if (nptr[0] == 'n' && strcmp(nptr,"nan") == 0)
     268              38 :         return NAN;
     269                 : 
     270                 : /* -------------------------------------------------------------------- */
     271                 : /*  We are implementing a simple method here: copy the input string     */
     272                 : /*  into the temporary buffer, replace the specified decimal delimiter  */
     273                 : /*  with the one, taken from locale settings and use standard strtod()  */
     274                 : /*  on that buffer.                                                     */
     275                 : /* -------------------------------------------------------------------- */
     276                 :     double      dfValue;
     277                 :     int         nError;
     278                 : 
     279         2914540 :     char*       pszNumber = CPLReplacePointByLocalePoint(nptr, point);
     280                 : 
     281         2914540 :     dfValue = strtod( pszNumber, endptr );
     282         2914540 :     nError = errno;
     283                 : 
     284         2914540 :     if ( endptr )
     285           19920 :         *endptr = (char *)nptr + (*endptr - pszNumber);
     286                 : 
     287         2914540 :     if (pszNumber != (char*) nptr)
     288             378 :         CPLFree( pszNumber );
     289                 : 
     290         2914540 :     errno = nError;
     291         2914540 :     return dfValue;
     292                 : }
     293                 : 
     294                 : /************************************************************************/
     295                 : /*                             CPLStrtod()                              */
     296                 : /************************************************************************/
     297                 : 
     298                 : /**
     299                 :  * Converts ASCII string to floating point number.
     300                 :  *
     301                 :  * This function converts the initial portion of the string pointed to
     302                 :  * by nptr to double floating point representation. This function does the
     303                 :  * same as standard strtod(3), but does not take locale in account. That
     304                 :  * means, the decimal delimiter is always '.' (decimal point). Use
     305                 :  * CPLStrtodDelim() function if you want to specify custom delimiter. Also
     306                 :  * see notes for CPLAtof() function.
     307                 :  *
     308                 :  * @param nptr Pointer to string to convert.
     309                 :  * @param endptr If is not NULL, a pointer to the character after the last
     310                 :  * character used in the conversion is stored in the location referenced
     311                 :  * by endptr.
     312                 :  *
     313                 :  * @return Converted value, if any.
     314                 :  */
     315         2217082 : double CPLStrtod(const char *nptr, char **endptr)
     316                 : {
     317         2217082 :     return CPLStrtodDelim(nptr, endptr, '.');
     318                 : }
     319                 : 
     320                 : /************************************************************************/
     321                 : /*                          CPLStrtofDelim()                            */
     322                 : /************************************************************************/
     323                 : 
     324                 : /**
     325                 :  * Converts ASCII string to floating point number using specified delimiter.
     326                 :  *
     327                 :  * This function converts the initial portion of the string pointed to
     328                 :  * by nptr to single floating point representation. This function does the
     329                 :  * same as standard strtof(3), but does not take locale in account. Instead of
     330                 :  * locale defined decimal delimiter you can specify your own one. Also see
     331                 :  * notes for CPLAtof() function.
     332                 :  *
     333                 :  * @param nptr Pointer to string to convert.
     334                 :  * @param endptr If is not NULL, a pointer to the character after the last
     335                 :  * character used in the conversion is stored in the location referenced
     336                 :  * by endptr.
     337                 :  * @param point Decimal delimiter.
     338                 :  *
     339                 :  * @return Converted value, if any.
     340                 :  */
     341               0 : float CPLStrtofDelim(const char *nptr, char **endptr, char point)
     342                 : {
     343                 : #if defined(HAVE_STRTOF)
     344                 : /* -------------------------------------------------------------------- */
     345                 : /*  We are implementing a simple method here: copy the input string     */
     346                 : /*  into the temporary buffer, replace the specified decimal delimiter  */
     347                 : /*  with the one, taken from locale settings and use standard strtof()  */
     348                 : /*  on that buffer.                                                     */
     349                 : /* -------------------------------------------------------------------- */
     350                 : 
     351                 :     double      dfValue;
     352                 :     int         nError;
     353                 : 
     354               0 :     char*       pszNumber = CPLReplacePointByLocalePoint(nptr, point);
     355                 : 
     356               0 :     dfValue = strtof( pszNumber, endptr );
     357               0 :     nError = errno;
     358                 : 
     359               0 :     if ( endptr )
     360               0 :         *endptr = (char *)nptr + (*endptr - pszNumber);
     361                 : 
     362               0 :     if (pszNumber != (char*) nptr)
     363               0 :         CPLFree( pszNumber );
     364                 : 
     365               0 :     errno = nError;
     366               0 :     return dfValue;
     367                 : 
     368                 : #else
     369                 : 
     370                 :     return (float)CPLStrtodDelim(nptr, endptr, point);
     371                 : 
     372                 : #endif /* HAVE_STRTOF */
     373                 : }
     374                 : 
     375                 : /************************************************************************/
     376                 : /*                             CPLStrtof()                              */
     377                 : /************************************************************************/
     378                 : 
     379                 : /**
     380                 :  * Converts ASCII string to floating point number.
     381                 :  *
     382                 :  * This function converts the initial portion of the string pointed to
     383                 :  * by nptr to single floating point representation. This function does the
     384                 :  * same as standard strtof(3), but does not take locale in account. That
     385                 :  * means, the decimal delimiter is always '.' (decimal point). Use
     386                 :  * CPLStrtofDelim() function if you want to specify custom delimiter. Also
     387                 :  * see notes for CPLAtof() function.
     388                 :  *
     389                 :  * @param nptr Pointer to string to convert.
     390                 :  * @param endptr If is not NULL, a pointer to the character after the last
     391                 :  * character used in the conversion is stored in the location referenced
     392                 :  * by endptr.
     393                 :  *
     394                 :  * @return Converted value, if any.
     395                 :  */
     396               0 : float CPLStrtof(const char *nptr, char **endptr)
     397                 : {
     398               0 :     return CPLStrtofDelim(nptr, endptr, '.');
     399                 : }
     400                 : 
     401                 : /* END OF FILE */

Generated by: LCOV version 1.7