LTP GCOV extension - code coverage report
Current view: directory - port - cpl_strtod.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 49
Code covered: 69.4 % Executed lines: 34

       1                 : /******************************************************************************
       2                 :  * $Id: cpl_strtod.cpp 19692 2010-05-13 17:16:55Z 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 19692 2010-05-13 17:16:55Z 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                 : /************************************************************************/
      64                 : /*                            CPLAtofDelim()                            */
      65                 : /************************************************************************/
      66                 : 
      67                 : /**
      68                 :  * Converts ASCII string to floating point number.
      69                 :  *
      70                 :  * This function converts the initial portion of the string pointed to
      71                 :  * by nptr to double floating point representation. The behaviour is the
      72                 :  * same as
      73                 :  *
      74                 :  *   CPLStrtodDelim(nptr, (char **)NULL, point);
      75                 :  *
      76                 :  * This function does the same as standard atof(3), but does not take locale
      77                 :  * in account. Instead of locale defined decimal delimiter you can specify
      78                 :  * your own one. Also see notes for CPLAtof() function.
      79                 :  *
      80                 :  * @param nptr Pointer to string to convert.
      81                 :  * @param point Decimal delimiter.
      82                 :  *
      83                 :  * @return Converted value, if any.
      84                 :  */
      85               0 : double CPLAtofDelim(const char *nptr, char point)
      86                 : {
      87               0 :   return CPLStrtodDelim(nptr, 0, point);
      88                 : }
      89                 : 
      90                 : /************************************************************************/
      91                 : /*                              CPLAtof()                               */
      92                 : /************************************************************************/
      93                 : 
      94                 : /**
      95                 :  * Converts ASCII string to floating point number.
      96                 :  *
      97                 :  * This function converts the initial portion of the string pointed to
      98                 :  * by nptr to double floating point representation. The behaviour is the
      99                 :  * same as
     100                 :  *
     101                 :  *   CPLStrtod(nptr, (char **)NULL);
     102                 :  *
     103                 :  * This function does the same as standard atof(3), but does not take
     104                 :  * locale in account. That means, the decimal delimiter is always '.'
     105                 :  * (decimal point). Use CPLAtofDelim() function if you want to specify
     106                 :  * custom delimiter.
     107                 :  *
     108                 :  * IMPORTANT NOTE.
     109                 :  * Existance of this function does not mean you should always use it.
     110                 :  * Sometimes you should use standard locale aware atof(3) and its family. When
     111                 :  * you need to process the user's input (for example, command line parameters)
     112                 :  * use atof(3), because user works in localized environment and her input will
     113                 :  * be done accordingly the locale set. In particular that means we should not
     114                 :  * make assumptions about character used as decimal delimiter, it can be
     115                 :  * either "." or ",".
     116                 :  * But when you are parsing some ASCII file in predefined format, you most
     117                 :  * likely need CPLAtof(), because such files distributed across the systems
     118                 :  * with different locales and floating point representation shoudl be
     119                 :  * considered as a part of file format. If the format uses "." as a delimiter
     120                 :  * the same character must be used when parsing number regardless of actual
     121                 :  * locale setting.
     122                 :  *
     123                 :  * @param nptr Pointer to string to convert.
     124                 :  *
     125                 :  * @return Converted value, if any.
     126                 :  */
     127          307176 : double CPLAtof(const char *nptr)
     128                 : {
     129          307176 :   return CPLStrtod(nptr, 0);
     130                 : }
     131                 : 
     132                 : /************************************************************************/
     133                 : /*                              CPLAtofM()                              */
     134                 : /************************************************************************/
     135                 : 
     136                 : /**
     137                 :  * Converts ASCII string to floating point number using any numeric locale.
     138                 :  *
     139                 :  * This function converts the initial portion of the string pointed to
     140                 :  * by nptr to double floating point representation. This function does the
     141                 :  * same as standard atof(), but it allows a variety of locale representations.
     142                 :  * That is it supports numeric values with either a comma or a period for 
     143                 :  * the decimal delimiter. 
     144                 :  * 
     145                 :  * PS. The M stands for Multi-lingual.
     146                 :  *
     147                 :  * @param nptr The string to convert.
     148                 :  *
     149                 :  * @return Converted value, if any.  Zero on failure.
     150                 :  */
     151                 : 
     152          345966 : double CPLAtofM( const char *nptr )
     153                 : 
     154                 : {
     155                 :     int i;
     156                 :     const static int nMaxSearch = 50;
     157                 : 
     158         2122805 :     for( i = 0; i < nMaxSearch; i++ )
     159                 :     {
     160         2122805 :         if( nptr[i] == ',' )
     161             192 :             return CPLStrtodDelim( nptr, 0, ',' );
     162         2122613 :         else if( nptr[i] == '.' || nptr[i] == '\0' )
     163          345774 :             return CPLStrtodDelim( nptr, 0, '.' );
     164                 :     }
     165                 : 
     166               0 :     return CPLStrtodDelim( nptr, 0, '.' );
     167                 : }
     168                 : 
     169                 : /************************************************************************/
     170                 : /*                          CPLStrtodDelim()                            */
     171                 : /************************************************************************/
     172                 : 
     173          662143 : static void CPLReplacePointByLocalePoint(char* pszNumber, char point)
     174                 : {
     175                 : #if defined(WIN32CE)
     176                 :     static char byPoint = 0;
     177                 :     if (byPoint == 0)
     178                 :     {
     179                 :         char szBuf[16];
     180                 :         sprintf(szBuf, "%.1f", 1.0);
     181                 :         byPoint = szBuf[1];
     182                 :     }
     183                 :     if (point != byPoint)
     184                 :     {
     185                 :         int     i = 0;
     186                 : 
     187                 :         while ( pszNumber[i] )
     188                 :         {
     189                 :             if ( pszNumber[i] == point )
     190                 :             {
     191                 :                 pszNumber[i] = byPoint;
     192                 :                 break;
     193                 :             }
     194                 :             i++;
     195                 :         }
     196                 :     }
     197                 : #else
     198          662143 :     struct lconv *poLconv = localeconv();
     199          662143 :     if ( poLconv
     200                 :          && poLconv->decimal_point
     201                 :          && strlen(poLconv->decimal_point) > 0 )
     202                 :     {
     203          662143 :         int     i = 0;
     204          662143 :         char    byPoint = poLconv->decimal_point[0];
     205                 : 
     206          662143 :         if (point != byPoint)
     207                 :         {
     208             419 :             while ( pszNumber[i] )
     209                 :             {
     210             227 :                 if ( pszNumber[i] == point )
     211                 :                 {
     212             192 :                     pszNumber[i] = byPoint;
     213             192 :                     break;
     214                 :                 }
     215              35 :                 i++;
     216                 :             }
     217                 :         }
     218                 :     }
     219                 : #endif
     220          662143 : }
     221                 : 
     222                 : 
     223                 : /**
     224                 :  * Converts ASCII string to floating point number using specified delimiter.
     225                 :  *
     226                 :  * This function converts the initial portion of the string pointed to
     227                 :  * by nptr to double floating point representation. This function does the
     228                 :  * same as standard strtod(3), but does not take locale in account. Instead of
     229                 :  * locale defined decimal delimiter you can specify your own one. Also see
     230                 :  * notes for CPLAtof() function.
     231                 :  *
     232                 :  * @param nptr Pointer to string to convert.
     233                 :  * @param endptr If is not NULL, a pointer to the character after the last
     234                 :  * character used in the conversion is stored in the location referenced
     235                 :  * by endptr.
     236                 :  * @param point Decimal delimiter.
     237                 :  *
     238                 :  * @return Converted value, if any.
     239                 :  */
     240          662174 : double CPLStrtodDelim(const char *nptr, char **endptr, char point)
     241                 : {
     242          662174 :    if (EQUAL(nptr,"nan") || EQUAL(nptr, "1.#QNAN") ||
     243                 :        EQUAL(nptr, "-1.#QNAN") || EQUAL(nptr, "-1.#IND"))
     244              31 :        return NAN;
     245                 : 
     246                 : /* -------------------------------------------------------------------- */
     247                 : /*  We are implementing a simple method here: copy the input string     */
     248                 : /*  into the temporary buffer, replace the specified decimal delimiter  */
     249                 : /*  with the one, taken from locale settings and use standard strtod()  */
     250                 : /*  on that buffer.                                                     */
     251                 : /* -------------------------------------------------------------------- */
     252          662143 :     char        *pszNumber = CPLStrdup( nptr );
     253                 :     double      dfValue;
     254                 :     int         nError;
     255                 : 
     256          662143 :     CPLReplacePointByLocalePoint(pszNumber, point);
     257                 : 
     258          662143 :     dfValue = strtod( pszNumber, endptr );
     259          662143 :     nError = errno;
     260                 : 
     261          662143 :     if ( endptr )
     262            9032 :         *endptr = (char *)nptr + (*endptr - pszNumber);
     263                 : 
     264          662143 :     CPLFree( pszNumber );
     265                 : 
     266          662143 :     errno = nError;
     267          662143 :     return dfValue;
     268                 : }
     269                 : 
     270                 : /************************************************************************/
     271                 : /*                             CPLStrtod()                              */
     272                 : /************************************************************************/
     273                 : 
     274                 : /**
     275                 :  * Converts ASCII string to floating point number.
     276                 :  *
     277                 :  * This function converts the initial portion of the string pointed to
     278                 :  * by nptr to double floating point representation. This function does the
     279                 :  * same as standard strtod(3), but does not take locale in account. That
     280                 :  * means, the decimal delimiter is always '.' (decimal point). Use
     281                 :  * CPLStrtodDelim() function if you want to specify custom delimiter. Also
     282                 :  * see notes for CPLAtof() function.
     283                 :  *
     284                 :  * @param nptr Pointer to string to convert.
     285                 :  * @param endptr If is not NULL, a pointer to the character after the last
     286                 :  * character used in the conversion is stored in the location referenced
     287                 :  * by endptr.
     288                 :  *
     289                 :  * @return Converted value, if any.
     290                 :  */
     291          316208 : double CPLStrtod(const char *nptr, char **endptr)
     292                 : {
     293          316208 :     return CPLStrtodDelim(nptr, endptr, '.');
     294                 : }
     295                 : 
     296                 : /************************************************************************/
     297                 : /*                          CPLStrtofDelim()                            */
     298                 : /************************************************************************/
     299                 : 
     300                 : /**
     301                 :  * Converts ASCII string to floating point number using specified delimiter.
     302                 :  *
     303                 :  * This function converts the initial portion of the string pointed to
     304                 :  * by nptr to single floating point representation. This function does the
     305                 :  * same as standard strtof(3), but does not take locale in account. Instead of
     306                 :  * locale defined decimal delimiter you can specify your own one. Also see
     307                 :  * notes for CPLAtof() function.
     308                 :  *
     309                 :  * @param nptr Pointer to string to convert.
     310                 :  * @param endptr If is not NULL, a pointer to the character after the last
     311                 :  * character used in the conversion is stored in the location referenced
     312                 :  * by endptr.
     313                 :  * @param point Decimal delimiter.
     314                 :  *
     315                 :  * @return Converted value, if any.
     316                 :  */
     317               0 : float CPLStrtofDelim(const char *nptr, char **endptr, char point)
     318                 : {
     319                 : #if defined(HAVE_STRTOF)
     320                 : /* -------------------------------------------------------------------- */
     321                 : /*  We are implementing a simple method here: copy the input string     */
     322                 : /*  into the temporary buffer, replace the specified decimal delimiter  */
     323                 : /*  with the one, taken from locale settings and use standard strtof()  */
     324                 : /*  on that buffer.                                                     */
     325                 : /* -------------------------------------------------------------------- */
     326                 : 
     327               0 :     char        *pszNumber = CPLStrdup( nptr );
     328                 :     double      dfValue;
     329                 :     int         nError;
     330                 : 
     331               0 :     CPLReplacePointByLocalePoint(pszNumber, point);
     332                 : 
     333               0 :     dfValue = strtof( pszNumber, endptr );
     334               0 :     nError = errno;
     335                 : 
     336               0 :     if ( endptr )
     337               0 :         *endptr = (char *)nptr + (*endptr - pszNumber);
     338                 : 
     339               0 :     CPLFree( pszNumber );
     340                 : 
     341               0 :     errno = nError;
     342               0 :     return dfValue;
     343                 : 
     344                 : #else
     345                 : 
     346                 :     return (float)CPLStrtodDelim(nptr, endptr, point);
     347                 : 
     348                 : #endif /* HAVE_STRTOF */
     349                 : }
     350                 : 
     351                 : /************************************************************************/
     352                 : /*                             CPLStrtof()                              */
     353                 : /************************************************************************/
     354                 : 
     355                 : /**
     356                 :  * Converts ASCII string to floating point number.
     357                 :  *
     358                 :  * This function converts the initial portion of the string pointed to
     359                 :  * by nptr to single floating point representation. This function does the
     360                 :  * same as standard strtof(3), but does not take locale in account. That
     361                 :  * means, the decimal delimiter is always '.' (decimal point). Use
     362                 :  * CPLStrtofDelim() function if you want to specify custom delimiter. Also
     363                 :  * see notes for CPLAtof() function.
     364                 :  *
     365                 :  * @param nptr Pointer to string to convert.
     366                 :  * @param endptr If is not NULL, a pointer to the character after the last
     367                 :  * character used in the conversion is stored in the location referenced
     368                 :  * by endptr.
     369                 :  *
     370                 :  * @return Converted value, if any.
     371                 :  */
     372               0 : float CPLStrtof(const char *nptr, char **endptr)
     373                 : {
     374               0 :     return CPLStrtofDelim(nptr, endptr, '.');
     375                 : }
     376                 : 
     377                 : /* END OF FILE */

Generated by: LTP GCOV extension version 1.5