diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2015-07-07 18:46:36 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2015-07-07 18:46:36 +0200 |
| commit | 2b5b97942016c2f18a0992b934d1b6b460391dac (patch) | |
| tree | 46cffbdad4a652422cc94f6077e3ab3955e6dc0f | |
| parent | 396afc3312243ff4a8e95c3b9398d56c5582e30d (diff) | |
| download | PROJ-2b5b97942016c2f18a0992b934d1b6b460391dac.tar.gz PROJ-2b5b97942016c2f18a0992b934d1b6b460391dac.zip | |
Make pj_init() locale safe and no longer modify locale (#226)
Remove setlocale() use in pj_init_ctx(), and replace uses of atof() &
strtod() by their locale safe variants pj_atof() and pj_strtod().
Proj versions from now advertize #define PJ_LOCALE_SAFE 1 in proj_api.h
and export pj_atof() & pj_strtod()
| -rw-r--r-- | ChangeLog | 6 | ||||
| -rw-r--r-- | cmake/Proj4Config.cmake | 3 | ||||
| -rw-r--r-- | cmake/proj_config.cmake.in | 3 | ||||
| -rwxr-xr-x | configure | 8 | ||||
| -rw-r--r-- | configure.in | 2 | ||||
| -rw-r--r-- | nad/Makefile.in | 7 | ||||
| -rwxr-xr-x | nad/testvarious | 10 | ||||
| -rw-r--r-- | src/Makefile.am | 3 | ||||
| -rw-r--r-- | src/Makefile.in | 7 | ||||
| -rw-r--r-- | src/cs2cs.c | 19 | ||||
| -rw-r--r-- | src/dmstor.c | 2 | ||||
| -rw-r--r-- | src/lib_proj.cmake | 2 | ||||
| -rw-r--r-- | src/makefile.vc | 6 | ||||
| -rw-r--r-- | src/pj_datum_set.c | 2 | ||||
| -rw-r--r-- | src/pj_gc_reader.c | 2 | ||||
| -rw-r--r-- | src/pj_init.c | 29 | ||||
| -rw-r--r-- | src/pj_param.c | 2 | ||||
| -rw-r--r-- | src/pj_strtod.c | 184 | ||||
| -rw-r--r-- | src/pj_utils.c | 11 | ||||
| -rw-r--r-- | src/proj.def | 2 | ||||
| -rw-r--r-- | src/proj_api.h | 4 | ||||
| -rw-r--r-- | src/proj_config.h.in | 16 | ||||
| -rw-r--r-- | src/projects.h | 5 |
23 files changed, 295 insertions, 40 deletions
@@ -1,3 +1,9 @@ +2015-07-27 Even Rouault <even.rouault@spatialys.com> + * : Remove setlocale() use in pj_init_ctx(), and replace uses of atof() & + strtod() by their locale safe variants pj_atof() and pj_strtod(). + Proj versions from now advertize #define PJ_LOCALE_SAFE 1 in proj_api.h + and export pj_atof() & pj_strtod() (#226) + 2015-02-21 Even Rouault <even.rouault@spatialys.com> * nad/epsg: regenerate nad/epsg with GDAL r28536 to avoid precision loss in TOWGS84 parameters, e.g. on Amersfoort / RD diff --git a/cmake/Proj4Config.cmake b/cmake/Proj4Config.cmake index e9aa1de5..fda9c9c2 100644 --- a/cmake/Proj4Config.cmake +++ b/cmake/Proj4Config.cmake @@ -9,6 +9,7 @@ ################################################################################ include (CheckIncludeFiles) include (CheckLibraryExists) +include (CheckFunctionExists) # check needed include file check_include_files (dlfcn.h HAVE_DLFCN_H) @@ -23,6 +24,8 @@ check_include_files (sys/types.h HAVE_SYS_TYPES_H) check_include_files (unistd.h HAVE_UNISTD_H) check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS) +CHECK_FUNCTION_EXISTS(localeconv HAVE_LOCALECONV) + # check libm need on unix check_library_exists(m ceil "" HAVE_LIBM) diff --git a/cmake/proj_config.cmake.in b/cmake/proj_config.cmake.in index 8f782a7c..bbdf3249 100644 --- a/cmake/proj_config.cmake.in +++ b/cmake/proj_config.cmake.in @@ -10,6 +10,9 @@ /* Define to 1 if you have the `m' library (-lm). */ #cmakedefine HAVE_LIBM 1 +/* Define to 1 if you have localeconv */ +#cmakedefine HAVE_LOCALECONV 1 + /* Define to 1 if you have the <memory.h> header file. */ #cmakedefine HAVE_MEMORY_H 1 @@ -12477,6 +12477,14 @@ $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi +ac_fn_c_check_func "$LINENO" "localeconv" "ac_cv_func_localeconv" +if test "x$ac_cv_func_localeconv" = xyes; then : + +$as_echo "#define HAVE_LOCALECONV 1" >>confdefs.h + +fi + + JNI_INCLUDE= export JNI_INCLUDE diff --git a/configure.in b/configure.in index fd7f3c03..b0f7176b 100644 --- a/configure.in +++ b/configure.in @@ -26,6 +26,8 @@ AC_CHECK_LIB(m,exp,,,) dnl We check for headers AC_HEADER_STDC +AC_CHECK_FUNC(localeconv, [AC_DEFINE(HAVE_LOCALECONV,1,[Define to 1 if you have localeconv])]) + dnl --------------------------------------------------------------------------- dnl Check for JNI support. dnl --------------------------------------------------------------------------- diff --git a/nad/Makefile.in b/nad/Makefile.in index 94437439..6cc682cb 100644 --- a/nad/Makefile.in +++ b/nad/Makefile.in @@ -272,15 +272,16 @@ TEST27 = $(NADPATH)/test27 TEST83 = $(NADPATH)/test83 TESTNTV2 = $(NADPATH)/testntv2 TESTVARIOUS = $(NADPATH)/testvarious +TESTFLAKY = $(NADPATH)/testflaky TESTDATUMFILE = $(NADPATH)/testdatumfile TESTIGN = $(NADPATH)/testIGNF -pkgdata_DATA = GL27 nad.lst nad27 nad83 world epsg esri \ +pkgdata_DATA = GL27 nad.lst proj_def.dat nad27 nad83 world epsg esri \ esri.extra other.extra \ CH IGNF EXTRA_DIST = GL27 nad.lst nad27 nad83 pj_out27.dist pj_out83.dist td_out.dist \ - test27 test83 world epsg esri tv_out.dist \ - testvarious testdatumfile testntv2 ntv2_out.dist \ + test27 test83 world epsg esri tv_out.dist tf_out.dist \ + testflaky testvarious testdatumfile testntv2 ntv2_out.dist \ esri.extra other.extra \ CH IGNF testIGNF proj_outIGNF.dist \ makefile.vc CMakeLists.txt diff --git a/nad/testvarious b/nad/testvarious index a128eb50..694d0d19 100755 --- a/nad/testvarious +++ b/nad/testvarious @@ -22,6 +22,16 @@ if test ! -x ${EXE}; then exit 1 fi +# Would be great to have a universale way of selecting a locale with +# a decimal separator that is not '.' +if command locale >/dev/null 2>/dev/null; then + if test `locale -a | grep fr_FR.utf8`; then + echo "Using locale with comma as decimal separator" + export LC_ALL=fr_FR.UTF-8 + export PROJ_USE_ENV_LOCALE=1 + fi +fi + echo "============================================" echo "Running ${0} using ${EXE}:" echo "============================================" diff --git a/src/Makefile.am b/src/Makefile.am index 2da16e7e..a996cbae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -70,7 +70,8 @@ libproj_la_SOURCES = \ nad_cvt.c nad_init.c nad_intr.c emess.c emess.h \ pj_apply_gridshift.c pj_datums.c pj_datum_set.c pj_transform.c \ geocent.c geocent.h pj_utils.c pj_gridinfo.c pj_gridlist.c \ - jniproj.c pj_mutex.c pj_initcache.c pj_apply_vgridshift.c geodesic.c + jniproj.c pj_mutex.c pj_initcache.c pj_apply_vgridshift.c geodesic.c \ + pj_strtod.c install-exec-local: rm -f $(DESTDIR)$(bindir)/invproj$(EXEEXT) diff --git a/src/Makefile.in b/src/Makefile.in index 8aa4143b..a71265df 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -161,7 +161,8 @@ am_libproj_la_OBJECTS = PJ_aeqd.lo PJ_gnom.lo PJ_laea.lo \ nad_intr.lo emess.lo pj_apply_gridshift.lo pj_datums.lo \ pj_datum_set.lo pj_transform.lo geocent.lo pj_utils.lo \ pj_gridinfo.lo pj_gridlist.lo jniproj.lo pj_mutex.lo \ - pj_initcache.lo pj_apply_vgridshift.lo geodesic.lo + pj_initcache.lo pj_apply_vgridshift.lo geodesic.lo \ + pj_strtod.lo libproj_la_OBJECTS = $(am_libproj_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -440,7 +441,8 @@ libproj_la_SOURCES = \ nad_cvt.c nad_init.c nad_intr.c emess.c emess.h \ pj_apply_gridshift.c pj_datums.c pj_datum_set.c pj_transform.c \ geocent.c geocent.h pj_utils.c pj_gridinfo.c pj_gridlist.c \ - jniproj.c pj_mutex.c pj_initcache.c pj_apply_vgridshift.c geodesic.c + jniproj.c pj_mutex.c pj_initcache.c pj_apply_vgridshift.c geodesic.c \ + pj_strtod.c all: proj_config.h $(MAKE) $(AM_MAKEFLAGS) all-am @@ -763,6 +765,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_qsfn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_release.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_strerrno.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_strtod.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_transform.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_tsfn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_units.Plo@am__quote@ diff --git a/src/cs2cs.c b/src/cs2cs.c index 43f7bf86..90369326 100644 --- a/src/cs2cs.c +++ b/src/cs2cs.c @@ -33,6 +33,7 @@ #include <string.h> #include <math.h> #include "emess.h" +#include <locale.h> #define MAX_LINE 1000 #define MAX_PARGS 100 @@ -167,6 +168,12 @@ int main(int argc, char **argv) FILE *fid; int from_argc=0, to_argc=0, eargc = 0, c, mon = 0; int have_to_flag = 0, inverse = 0, i; + int use_env_locale = 0; + + /* This is just to check that pj_init() is locale-safe */ + /* Used by nad/testvarious */ + if( getenv("PROJ_USE_ENV_LOCALE") != NULL ) + use_env_locale = 1; if ((emess_dat.Prog_name = strrchr(*argv,DIR_CHAR)) != NULL) ++emess_dat.Prog_name; @@ -336,6 +343,12 @@ int main(int argc, char **argv) to_argc = argcount; } + if( use_env_locale ) + { + /* Set locale from environment */ + setlocale(LC_ALL, ""); + } + if( from_argc == 0 && to_argc != 0 ) { /* we will generate the from proj as the latlong of the +to in a bit */ @@ -389,6 +402,12 @@ int main(int argc, char **argv) } } + if( use_env_locale ) + { + /* Restore C locale to avoid issues in parsing/outputing numbers*/ + setlocale(LC_ALL, "C"); + } + if (mon) { printf( "%c ---- From Coordinate System ----\n", tag ); pj_pr_list(fromProj); diff --git a/src/dmstor.c b/src/dmstor.c index f1da5379..62c06f3d 100644 --- a/src/dmstor.c +++ b/src/dmstor.c @@ -108,6 +108,6 @@ proj_strtod(char *nptr, char **endptr) /* no offending characters, just handle normally */ - return strtod(nptr, endptr); + return pj_strtod(nptr, endptr); } diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index 8111c7aa..8a6349d8 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -200,6 +200,7 @@ SET(SRC_LIBPROJ_CORE proj_rouss.c rtodms.c vector1.c + pj_strtod.c ${CMAKE_CURRENT_BINARY_DIR}/proj_config.h ) @@ -213,6 +214,7 @@ set(HEADERS_LIBPROJ source_group("Header Files" FILES ${HEADERS_LIBPROJ}) source_group("Source Files\\Core" FILES ${SRC_LIBPROJ_CORE}) source_group("Source Files\\PJ" FILES ${SRC_LIBPROJ_PJ}) +include_directories( ${CMAKE_CURRENT_BINARY_DIR}) source_group("CMake Files" FILES CMakeLists.txt) diff --git a/src/makefile.vc b/src/makefile.vc index 5e57c716..4a47f045 100644 --- a/src/makefile.vc +++ b/src/makefile.vc @@ -54,7 +54,9 @@ support = \ nad_cvt.obj nad_init.obj nad_intr.obj \ pj_utils.obj pj_gridlist.obj pj_gridinfo.obj \ proj_mdist.obj pj_mutex.obj pj_initcache.obj \ - pj_ctx.obj pj_fileapi.obj pj_log.obj pj_apply_vgridshift.obj + pj_ctx.obj pj_fileapi.obj pj_log.obj pj_apply_vgridshift.obj \ + pj_strtod.obj + geodesic = geodesic.obj LIBOBJ = $(support) $(pseudo) $(azimuthal) $(conic) $(cylinder) $(misc) \ $(geodesic) @@ -68,7 +70,7 @@ GEOD_EXE = geod.exe NAD2BIN_EXE = nad2bin.exe CFLAGS = /nologo -I. -DPROJ_LIB=\"$(PROJ_LIB_DIR)\" \ - -DHAVE_STRERROR=1 $(OPTFLAGS) + -DHAVE_STRERROR=1 -DHAVE_LOCALECONV=1 $(OPTFLAGS) default: all diff --git a/src/pj_datum_set.c b/src/pj_datum_set.c index 69b60469..194bfe57 100644 --- a/src/pj_datum_set.c +++ b/src/pj_datum_set.c @@ -118,7 +118,7 @@ int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef) /* parse out the parameters */ for( s = towgs84; *s != '\0' && parm_count < 7; ) { - projdef->datum_params[parm_count++] = atof(s); + projdef->datum_params[parm_count++] = pj_atof(s); while( *s != '\0' && *s != ',' ) s++; if( *s == ',' ) diff --git a/src/pj_gc_reader.c b/src/pj_gc_reader.c index 81d0fb26..458737c1 100644 --- a/src/pj_gc_reader.c +++ b/src/pj_gc_reader.c @@ -152,7 +152,7 @@ double pj_gc_parsedate( projCtx ctx, const char *date_string ) } else { - return atof(date_string); + return pj_atof(date_string); } } diff --git a/src/pj_init.c b/src/pj_init.c index 622e80bf..13d469da 100644 --- a/src/pj_init.c +++ b/src/pj_init.c @@ -32,7 +32,6 @@ #include <stdio.h> #include <string.h> #include <errno.h> -#include <locale.h> #include <ctype.h> typedef struct { @@ -389,25 +388,10 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { paralist *curr; int i; PJ *PIN = 0; - char *old_locale; ctx->last_errno = 0; start = NULL; - /* - ** MS Visual Studio 2012+ may have problems in multithreaded cases - ** as discussed in this ticket: - ** http://trac.osgeo.org/proj/ticket/226 - */ - old_locale = setlocale(LC_NUMERIC, NULL); - if (old_locale != NULL) { - if (strcmp(old_locale,"C") != 0) { - old_locale = strdup(old_locale); - setlocale(LC_NUMERIC,"C"); - }else - old_locale = NULL; - } - /* put arguments into internal linked list */ if (argc <= 0) { pj_ctx_set_errno( ctx, -1 ); goto bum_call; } start = curr = pj_mkparam(argv[0]); @@ -554,9 +538,9 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { s = pj_units[i].to_meter; } if (s || (s = pj_param(ctx, start, "sto_meter").s)) { - PIN->to_meter = strtod(s, &s); + PIN->to_meter = pj_strtod(s, &s); if (*s == '/') /* ratio number */ - PIN->to_meter /= strtod(++s, 0); + PIN->to_meter /= pj_strtod(++s, 0); PIN->fr_meter = 1. / PIN->to_meter; } else PIN->to_meter = PIN->fr_meter = 1.; @@ -569,9 +553,9 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { s = pj_units[i].to_meter; } if (s || (s = pj_param(ctx, start, "svto_meter").s)) { - PIN->vto_meter = strtod(s, &s); + PIN->vto_meter = pj_strtod(s, &s); if (*s == '/') /* ratio number */ - PIN->vto_meter /= strtod(++s, 0); + PIN->vto_meter /= pj_strtod(++s, 0); PIN->vfr_meter = 1. / PIN->vto_meter; } else { PIN->vto_meter = PIN->to_meter; @@ -617,11 +601,6 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { PIN = 0; } - if (old_locale != NULL) { - setlocale(LC_NUMERIC,old_locale); - free( (char*)old_locale ); - } - return PIN; } diff --git a/src/pj_param.c b/src/pj_param.c index 119006e1..ed6ce27c 100644 --- a/src/pj_param.c +++ b/src/pj_param.c @@ -61,7 +61,7 @@ pj_param(projCtx ctx, paralist *pl, const char *opt) { value.i = atoi(opt); break; case 'd': /* simple real input */ - value.f = atof(opt); + value.f = pj_atof(opt); break; case 'r': /* degrees input */ value.f = dmstor_ctx(ctx, opt, 0); diff --git a/src/pj_strtod.c b/src/pj_strtod.c new file mode 100644 index 00000000..9aac07e5 --- /dev/null +++ b/src/pj_strtod.c @@ -0,0 +1,184 @@ +/****************************************************************************** + * + * Derived from GDAL port/cpl_strtod.cpp + * Purpose: Functions to convert ASCII string to floating point number. + * Author: Andrey Kiselev, dron@ak4719.spb.edu. + * + ****************************************************************************** + * Copyright (c) 2006, Andrey Kiselev + * Copyright (c) 2008-2012, Even Rouault <even dot rouault at mines-paris dot org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#include "projects.h" + +/* Windows nmake build doesn't have a proj_config.h, but HAVE_LOCALECONV */ +/* is defined in the compilation line */ +#ifndef HAVE_LOCALECONV +#include "proj_config.h" +#endif + +#include <stdlib.h> +#include <locale.h> +#include <errno.h> + +#define PJ_STRTOD_WORK_BUFFER_SIZE 64 + +/************************************************************************/ +/* pj_atof() */ +/************************************************************************/ + +/** + * Converts ASCII string to floating point number. + * + * This function converts the initial portion of the string pointed to + * by nptr to double floating point representation. The behaviour is the + * same as + * + * pj_strtod(nptr, (char **)NULL); + * + * This function does the same as standard atof(3), but does not take + * locale in account. That means, the decimal delimiter is always '.' + * (decimal point). + * + * @param nptr Pointer to string to convert. + * + * @return Converted value. + */ +double pj_atof( const char* nptr ) +{ + return pj_strtod(nptr, NULL); +} + + +/************************************************************************/ +/* pj_replace_point_by_locale_point() */ +/************************************************************************/ + +static char* pj_replace_point_by_locale_point(const char* pszNumber, char point, + char* pszWorkBuffer) +{ +#if !defined(HAVE_LOCALECONV) || defined(_WIN32_WCE) +#warning "localeconv not available" + static char byPoint = 0; + if (byPoint == 0) + { + char szBuf[16]; + sprintf(szBuf, "%.1f", 1.0); + byPoint = szBuf[1]; + } + if (point != byPoint) + { + const char* pszPoint = strchr(pszNumber, point); + if (pszPoint) + { + char* pszNew; + if( strlen(pszNumber) < PJ_STRTOD_WORK_BUFFER_SIZE ) + { + strcpy(pszWorkBuffer, pszNumber); + pszNew = pszWorkBuffer; + } + else + pszNew = strdup(pszNumber); + pszNew[pszPoint - pszNumber] = byPoint; + return pszNew; + } + } +#else + struct lconv *poLconv = localeconv(); + if ( poLconv + && poLconv->decimal_point + && poLconv->decimal_point[0] != '\0' ) + { + char byPoint = poLconv->decimal_point[0]; + + if (point != byPoint) + { + const char* pszLocalePoint = strchr(pszNumber, byPoint); + const char* pszPoint = strchr(pszNumber, point); + if (pszPoint || pszLocalePoint) + { + char* pszNew; + if( strlen(pszNumber) < PJ_STRTOD_WORK_BUFFER_SIZE ) + { + strcpy(pszWorkBuffer, pszNumber); + pszNew = pszWorkBuffer; + } + else + pszNew = strdup(pszNumber); + if( pszLocalePoint ) + pszNew[pszLocalePoint - pszNumber] = ' '; + if( pszPoint ) + pszNew[pszPoint - pszNumber] = byPoint; + return pszNew; + } + } + } +#endif + return (char*) pszNumber; +} + +/************************************************************************/ +/* pj_strtod() */ +/************************************************************************/ + +/** + * Converts ASCII string to floating point number. + * + * This function converts the initial portion of the string pointed to + * by nptr to double floating point representation. This function does the + * same as standard strtod(3), but does not take locale in account and use + * decimal point. + * + * @param nptr Pointer to string to convert. + * @param endptr If is not NULL, a pointer to the character after the last + * character used in the conversion is stored in the location referenced + * by endptr. + * @param point Decimal delimiter. + * + * @return Converted value. + */ +double pj_strtod( const char *nptr, char **endptr ) +{ +/* -------------------------------------------------------------------- */ +/* We are implementing a simple method here: copy the input string */ +/* into the temporary buffer, replace the specified decimal delimiter */ +/* with the one, taken from locale settings and use standard strtod() */ +/* on that buffer. */ +/* -------------------------------------------------------------------- */ + double dfValue; + int nError; + char szWorkBuffer[PJ_STRTOD_WORK_BUFFER_SIZE]; + + char* pszNumber = pj_replace_point_by_locale_point(nptr, '.', szWorkBuffer); + + dfValue = strtod( pszNumber, endptr ); + nError = errno; + + if ( endptr ) + *endptr = (char *)nptr + (*endptr - pszNumber); + + if (pszNumber != (char*) nptr && pszNumber != szWorkBuffer ) + free( pszNumber ); + + errno = nError; + return dfValue; +} + diff --git a/src/pj_utils.c b/src/pj_utils.c index bb4b6ae6..f11081fc 100644 --- a/src/pj_utils.c +++ b/src/pj_utils.c @@ -101,8 +101,15 @@ PJ *pj_latlong_from_proj( PJ *pj_in ) sprintf( defn+strlen(defn), " +f=%s", pj_param(pj_in->ctx,pj_in->params,"sf").s ); else - sprintf( defn+strlen(defn), " +es=%.16g", - pj_in->es ); + { + char* ptr = defn+strlen(defn); + sprintf( ptr, " +es=%.16g", pj_in->es ); + for(; *ptr; ptr++) + { + if( *ptr == ',' ) + *ptr = '.'; + } + } } else { diff --git a/src/proj.def b/src/proj.def index bfcf9f94..f3146551 100644 --- a/src/proj.def +++ b/src/proj.def @@ -72,3 +72,5 @@ EXPORTS pj_ctx_ftell @70 pj_ctx_fclose @71 pj_open_lib @72 + pj_atof @73 + pj_strtod @74 diff --git a/src/proj_api.h b/src/proj_api.h index 0c4be974..ed11d6a4 100644 --- a/src/proj_api.h +++ b/src/proj_api.h @@ -40,6 +40,10 @@ extern "C" { /* Try to update this every version! */ #define PJ_VERSION 491 +/* pj_init() and similar functions can be used with a non-C locale */ +/* Can be detected too at runtime if the symbol pj_atof exists */ +#define PJ_LOCALE_SAFE 1 + extern char const pj_release[]; /* global release id string */ #define RAD_TO_DEG 57.29577951308232 diff --git a/src/proj_config.h.in b/src/proj_config.h.in index e4992e2c..7a8d6943 100644 --- a/src/proj_config.h.in +++ b/src/proj_config.h.in @@ -6,9 +6,18 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the <jni.h> header file. */ +#undef HAVE_JNI_H + /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have localeconv */ +#undef HAVE_LOCALECONV + /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H @@ -36,6 +45,10 @@ /* Enabled for Java/JNI Support */ #undef JNI_ENABLED +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + /* Name of package */ #undef PACKAGE @@ -51,6 +64,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION diff --git a/src/projects.h b/src/projects.h index 062bd07d..ac95f69d 100644 --- a/src/projects.h +++ b/src/projects.h @@ -509,7 +509,10 @@ struct PJ_DATUMS *pj_get_datums_ref( void ); struct PJ_UNITS *pj_get_units_ref( void ); struct PJ_LIST *pj_get_list_ref( void ); struct PJ_PRIME_MERIDIANS *pj_get_prime_meridians_ref( void ); - + +double pj_atof( const char* nptr ); +double pj_strtod( const char *nptr, char **endptr ); + #ifdef __cplusplus } #endif |
