aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrank Warmerdam <warmerdam@pobox.com>2010-06-11 01:51:24 +0000
committerFrank Warmerdam <warmerdam@pobox.com>2010-06-11 01:51:24 +0000
commitec678c07c2acb83da8a2187c541b8a2e452dec4b (patch)
treea4c004a6e88d7330fe9d1c6ed793129831b5bdca /src
parenta7290836114dc82b35eceb1efcb5ecdf605d335f (diff)
downloadPROJ-ec678c07c2acb83da8a2187c541b8a2e452dec4b.tar.gz
PROJ-ec678c07c2acb83da8a2187c541b8a2e452dec4b.zip
preliminary implementation of projCtx API
git-svn-id: http://svn.osgeo.org/metacrs/proj/trunk@1854 4e78687f-474d-0410-85f9-8d5e500ac6b2
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.in10
-rw-r--r--src/PJ_tmerc.c4
-rw-r--r--src/cs2cs.c4
-rw-r--r--src/geod_set.c2
-rw-r--r--src/multistresstest.c111
-rw-r--r--src/nad2nad.c4
-rw-r--r--src/nad_init.c21
-rw-r--r--src/pj_apply_gridshift.c55
-rw-r--r--src/pj_apply_vgridshift.c15
-rw-r--r--src/pj_ctx.c179
-rw-r--r--src/pj_datum_set.c4
-rw-r--r--src/pj_ell_set.c14
-rw-r--r--src/pj_factors.c4
-rw-r--r--src/pj_fwd.c9
-rw-r--r--src/pj_gridinfo.c93
-rw-r--r--src/pj_gridlist.c14
-rw-r--r--src/pj_init.c71
-rw-r--r--src/pj_inv.c8
-rw-r--r--src/pj_log.c73
-rw-r--r--src/pj_open_lib.c10
-rw-r--r--src/pj_transform.c111
-rw-r--r--src/pj_utils.c4
-rw-r--r--src/proj_api.h26
-rw-r--r--src/projects.h32
25 files changed, 640 insertions, 240 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 0dcf782f..b82b89b9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -54,7 +54,7 @@ libproj_la_SOURCES = \
pj_factors.c pj_fwd.c pj_init.c pj_inv.c \
pj_list.c pj_malloc.c pj_mlfn.c pj_msfn.c proj_mdist.c \
pj_open_lib.c pj_param.c pj_phi2.c pj_pr_list.c \
- pj_qsfn.c pj_strerrno.c pj_tsfn.c pj_units.c \
+ pj_qsfn.c pj_strerrno.c pj_tsfn.c pj_units.c pj_ctx.c pj_log.c \
pj_zpoly1.c rtodms.c vector1.c pj_release.c pj_gauss.c \
\
nad_cvt.c nad_init.c nad_intr.c emess.c emess.h \
diff --git a/src/Makefile.in b/src/Makefile.in
index b9310071..b2cda0cb 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -99,9 +99,9 @@ am_libproj_la_OBJECTS = PJ_aeqd.lo PJ_gnom.lo PJ_laea.lo \
pj_init.lo pj_inv.lo pj_list.lo pj_malloc.lo pj_mlfn.lo \
pj_msfn.lo proj_mdist.lo pj_open_lib.lo pj_param.lo pj_phi2.lo \
pj_pr_list.lo pj_qsfn.lo pj_strerrno.lo pj_tsfn.lo pj_units.lo \
- pj_zpoly1.lo rtodms.lo vector1.lo pj_release.lo pj_gauss.lo \
- nad_cvt.lo nad_init.lo nad_intr.lo emess.lo \
- pj_apply_gridshift.lo pj_datums.lo pj_datum_set.lo \
+ pj_ctx.lo pj_log.lo pj_zpoly1.lo rtodms.lo vector1.lo \
+ pj_release.lo pj_gauss.lo nad_cvt.lo nad_init.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
@@ -310,7 +310,7 @@ libproj_la_SOURCES = \
pj_factors.c pj_fwd.c pj_init.c pj_inv.c \
pj_list.c pj_malloc.c pj_mlfn.c pj_msfn.c proj_mdist.c \
pj_open_lib.c pj_param.c pj_phi2.c pj_pr_list.c \
- pj_qsfn.c pj_strerrno.c pj_tsfn.c pj_units.c \
+ pj_qsfn.c pj_strerrno.c pj_tsfn.c pj_units.c pj_ctx.c pj_log.c \
pj_zpoly1.c rtodms.c vector1.c pj_release.c pj_gauss.c \
\
nad_cvt.c nad_init.c nad_intr.c emess.c emess.h \
@@ -582,6 +582,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_apply_gridshift.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_apply_vgridshift.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_auth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_ctx.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_datum_set.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_datums.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_deriv.Plo@am__quote@
@@ -599,6 +600,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_inv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_latlong.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_list.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_log.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_malloc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_mlfn.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_msfn.Plo@am__quote@
diff --git a/src/PJ_tmerc.c b/src/PJ_tmerc.c
index 14cf2e8e..5104608a 100644
--- a/src/PJ_tmerc.c
+++ b/src/PJ_tmerc.c
@@ -32,7 +32,7 @@ FORWARD(e_forward); /* ellipse */
{
xy.x = HUGE_VAL;
xy.y = HUGE_VAL;
- pj_errno = -14;
+ pj_ctx_set_errno( P->ctx, -14 );
return xy;
}
@@ -70,7 +70,7 @@ FORWARD(s_forward); /* sphere */
{
xy.x = HUGE_VAL;
xy.y = HUGE_VAL;
- pj_errno = -14;
+ pj_ctx_set_errno( P->ctx, -14 );
return xy;
}
diff --git a/src/cs2cs.c b/src/cs2cs.c
index f698afe9..74b44750 100644
--- a/src/cs2cs.c
+++ b/src/cs2cs.c
@@ -284,6 +284,10 @@ int main(int argc, char **argv)
case 's': /* reverse output */
reverseout = 1;
continue;
+ case 'd': /* set debug level */
+ if (--argc <= 0) goto noargument;
+ pj_ctx_set_debug( pj_get_default_ctx(), atoi(*++argv));
+ continue;
default:
emess(1, "invalid option: -%c",*arg);
break;
diff --git a/src/geod_set.c b/src/geod_set.c
index 88217277..ba2b415e 100644
--- a/src/geod_set.c
+++ b/src/geod_set.c
@@ -21,7 +21,7 @@ geod_set(int argc, char **argv) {
else
start = curr = pj_mkparam(argv[i]);
/* set elliptical parameters */
- if (pj_ell_set(start, &geod_a, &es)) emess(1,"ellipse setup failure");
+ if (pj_ell_set(pj_get_default_ctx(),start, &geod_a, &es)) emess(1,"ellipse setup failure");
/* set units */
if (name = pj_param(start, "sunits").s) {
char *s;
diff --git a/src/multistresstest.c b/src/multistresstest.c
index ddd483ff..61cbc821 100644
--- a/src/multistresstest.c
+++ b/src/multistresstest.c
@@ -32,9 +32,15 @@
#include <unistd.h>
#include "proj_api.h"
+#define num_threads 10
+#define num_iterations 100000
+#define reinit_every_iteration 0
+
typedef struct {
const char *src_def;
const char *dst_def;
+
+ int skip;
double src_x, src_y, src_z;
double dst_x, dst_y, dst_z;
@@ -58,24 +64,57 @@ TestItem test_list[] = {
"+proj=merc +datum=potsdam",
150000.0, 3000000.0, 0.0,
},
-
-/*
-** This test currentsly sets pj_errno and messes up the others. It
-** should be re-enabled when the pj_errno conflict is resolved.
-*/
-#ifdef notdef
{
"+proj=latlong +nadgrids=nzgd2kgrid0005.gsb",
"+proj=latlong +datum=WGS84",
150000.0, 3000000.0, 0.0,
},
-#endif
{
"+proj=latlong +nadgrids=nzgd2kgrid0005.gsb",
"+proj=latlong +datum=WGS84",
170 * DEG_TO_RAD, -40 * DEG_TO_RAD, 0.0,
},
{
+ "+proj=latlong +ellps=GRS80 +towgs84=2,3,5",
+ "+proj=latlong +ellps=intl +towgs84=10,12,15",
+ 170 * DEG_TO_RAD, -40 * DEG_TO_RAD, 0.0,
+ },
+ {
+ "+proj=eqc +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
+ "+proj=stere +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
+ 150000.0, 250000.0, 0.0,
+ },
+ {
+ "+proj=cea +lat_ts=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
+ "+proj=merc +lon_0=12 +k=0.999 +x_0=100000 +y_0=200000 +datum=WGS84 ",
+ 150000.0, 250000.0, 0.0,
+ },
+ {
+ "+proj=bonne +lat_1=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
+ "+proj=cass +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
+ 150000.0, 250000.0, 0.0,
+ },
+ {
+ "+proj=nzmg +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
+ "+proj=gnom +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
+ 150000.0, 250000.0, 0.0,
+ },
+ {
+ "+proj=ortho +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
+ "+proj=laea +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
+ 150000.0, 250000.0, 0.0,
+ },
+ {
+ "+proj=aeqd +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
+ "+proj=eqdc +lat_1=20 +lat_2=5 +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
+ 150000.0, 250000.0, 0.0,
+ },
+ {
+ "+proj=mill +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
+ "+proj=moll +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
+ 150000.0, 250000.0, 0.0,
+ },
+ {
"+init=epsg:3309",
"+init=epsg:4326",
150000.0, 30000.0, 0.0,
@@ -97,22 +136,26 @@ static void *TestThread( void *pData )
/* Initialize coordinate system definitions. */
/* -------------------------------------------------------------------- */
projPJ *src_pj_list, *dst_pj_list;
+ projCtx ctx = pj_ctx_alloc();
+// projCtx ctx = pj_get_default_ctx();
src_pj_list = (projPJ *) calloc(test_count,sizeof(projPJ));
dst_pj_list = (projPJ *) calloc(test_count,sizeof(projPJ));
+#if reinit_every_iteration == 0
for( i = 0; i < test_count; i++ )
{
TestItem *test = test_list + i;
- src_pj_list[i] = pj_init_plus( test->src_def );
- dst_pj_list[i] = pj_init_plus( test->dst_def );
+ src_pj_list[i] = pj_init_plus_ctx( ctx, test->src_def );
+ dst_pj_list[i] = pj_init_plus_ctx( ctx, test->dst_def );
}
+#endif
/* -------------------------------------------------------------------- */
/* Perform tests - over and over. */
/* -------------------------------------------------------------------- */
- int repeat_count = 100000, i_iter;
+ int repeat_count = num_iterations, i_iter;
for( i_iter = 0; i_iter < repeat_count; i_iter++ )
{
@@ -121,11 +164,19 @@ static void *TestThread( void *pData )
TestItem *test = test_list + i;
double x, y, z;
int error;
+
+ if( test->skip )
+ continue;
x = test->src_x;
y = test->src_y;
z = test->src_z;
+#if reinit_every_iteration == 1
+ src_pj_list[i] = pj_init_plus_ctx( ctx, test->src_def );
+ dst_pj_list[i] = pj_init_plus_ctx( ctx, test->dst_def );
+#endif
+
error = pj_transform( src_pj_list[i], dst_pj_list[i], 1, 0,
&x, &y, &z );
@@ -144,9 +195,31 @@ static void *TestThread( void *pData )
x, y, z,
test->dst_x, test->dst_y, test->dst_z );
}
+
+#if reinit_every_iteration == 1
+ pj_free( src_pj_list[i] );
+ pj_free( dst_pj_list[i] );
+#endif
}
}
+/* -------------------------------------------------------------------- */
+/* Cleanup */
+/* -------------------------------------------------------------------- */
+#if reinit_every_iteration == 0
+ for( i = 0; i < test_count; i++ )
+ {
+ TestItem *test = test_list + i;
+ pj_free( src_pj_list[i] );
+ pj_free( dst_pj_list[i] );
+ }
+#endif
+
+ free( src_pj_list );
+ free( dst_pj_list );
+
+ pj_ctx_free( ctx );
+
printf( "%d iterations of the %d tests complete in thread X\n",
repeat_count, test_count );
@@ -173,6 +246,20 @@ int main( int argc, char **argv )
src_pj = pj_init_plus( test->src_def );
dst_pj = pj_init_plus( test->dst_def );
+
+ if( src_pj == NULL )
+ {
+ printf( "Unable to translate:\n%s\n", test->src_def );
+ test->skip = 1;
+ continue;
+ }
+
+ if( dst_pj == NULL )
+ {
+ printf( "Unable to translate:\n%s\n", test->dst_def );
+ test->skip = 1;
+ continue;
+ }
test->dst_x = test->src_x;
test->dst_y = test->src_y;
@@ -185,6 +272,8 @@ int main( int argc, char **argv )
pj_free( src_pj );
pj_free( dst_pj );
+
+ test->skip = 0;
}
printf( "%d tests initialized.\n", test_count );
@@ -192,8 +281,6 @@ int main( int argc, char **argv )
/* -------------------------------------------------------------------- */
/* Now launch a bunch of threads to repeat the tests. */
/* -------------------------------------------------------------------- */
-#define num_threads 2
-
pthread_t ahThread[num_threads];
pthread_attr_t hThreadAttr;
diff --git a/src/nad2nad.c b/src/nad2nad.c
index e59877da..43a2eccd 100644
--- a/src/nad2nad.c
+++ b/src/nad2nad.c
@@ -63,7 +63,7 @@ set_zone(int in, struct IO_CON *io) {
if (io->hp) {
io->t83 = 1;
- if (!(htab = nad_init(io->hp)))
+ if (!(htab = nad_init(pj_get_default_ctx(), io->hp)))
emess(1,"hp datum file: %s, failed: %s", io->hp,
pj_strerrno(pj_errno));
}
@@ -98,7 +98,7 @@ setup() {
if (czone) {
if (!input.hp && !output.hp && input.t83 == output.t83)
emess(1,"identical datums");
- if (!(ctab = nad_init(czone)))
+ if (!(ctab = nad_init(pj_get_default_ctx(), czone)))
emess(1,"datum file: %s, failed: %s", czone, pj_strerrno(pj_errno));
} else if (input.t83 != output.t83)
emess(1,"conversion region (-r) not specified");
diff --git a/src/nad_init.c b/src/nad_init.c
index 56eb73d9..da10dd2b 100644
--- a/src/nad_init.c
+++ b/src/nad_init.c
@@ -50,7 +50,7 @@
/* Load the data portion of a ctable formatted grid. */
/************************************************************************/
-int nad_ctable_load( struct CTABLE *ct, FILE *fid )
+int nad_ctable_load( projCtx ctx, struct CTABLE *ct, FILE *fid )
{
int a_size;
@@ -72,7 +72,7 @@ int nad_ctable_load( struct CTABLE *ct, FILE *fid )
"ctable loading failed on fread() - binary incompatible?\n" );
}
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -85,7 +85,7 @@ int nad_ctable_load( struct CTABLE *ct, FILE *fid )
/* Read the header portion of a "ctable" format grid. */
/************************************************************************/
-struct CTABLE *nad_ctable_init( FILE * fid )
+struct CTABLE *nad_ctable_init( projCtx ctx, FILE * fid )
{
struct CTABLE *ct;
int id_end;
@@ -95,7 +95,7 @@ struct CTABLE *nad_ctable_init( FILE * fid )
if( ct == NULL
|| fread( ct, sizeof(struct CTABLE), 1, fid ) != 1 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return NULL;
}
@@ -103,7 +103,7 @@ struct CTABLE *nad_ctable_init( FILE * fid )
if( ct->lim.lam < 1 || ct->lim.lam > 100000
|| ct->lim.phi < 1 || ct->lim.phi > 100000 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return NULL;
}
@@ -127,27 +127,26 @@ struct CTABLE *nad_ctable_init( FILE * fid )
/* Read a datum shift file in any of the supported binary formats. */
/************************************************************************/
-struct CTABLE *nad_init(char *name)
+struct CTABLE *nad_init(projCtx ctx, char *name)
{
char fname[MAX_PATH_FILENAME+1];
struct CTABLE *ct;
FILE *fid;
- errno = pj_errno = 0;
+ ctx->last_errno = 0;
/* -------------------------------------------------------------------- */
/* Open the file using the usual search rules. */
/* -------------------------------------------------------------------- */
strcpy(fname, name);
- if (!(fid = pj_open_lib(fname, "rb"))) {
- pj_errno = errno;
+ if (!(fid = pj_open_lib(ctx, fname, "rb"))) {
return 0;
}
- ct = nad_ctable_init( fid );
+ ct = nad_ctable_init( ctx, fid );
if( ct != NULL )
{
- if( !nad_ctable_load( ct, fid ) )
+ if( !nad_ctable_load( ctx, ct, fid ) )
{
nad_free( ct );
ct = NULL;
diff --git a/src/pj_apply_gridshift.c b/src/pj_apply_gridshift.c
index 50ff6e6a..9ce9c02c 100644
--- a/src/pj_apply_gridshift.c
+++ b/src/pj_apply_gridshift.c
@@ -45,7 +45,7 @@
/* it to honour our public api. */
/************************************************************************/
-int pj_apply_gridshift( const char *nadgrids, int inverse,
+int pj_apply_gridshift( projCtx ctx, const char *nadgrids, int inverse,
long point_count, int point_offset,
double *x, double *y, double *z )
@@ -54,12 +54,12 @@ int pj_apply_gridshift( const char *nadgrids, int inverse,
int grid_count;
int ret;
- gridlist = pj_gridlist_from_nadgrids( nadgrids, &grid_count );
+ gridlist = pj_gridlist_from_nadgrids( ctx, nadgrids, &grid_count );
if( gridlist == NULL || grid_count == 0 )
- return pj_errno;
+ return ctx->last_errno;
- ret = pj_apply_gridshift_3( gridlist, grid_count, inverse,
+ ret = pj_apply_gridshift_3( ctx, gridlist, grid_count, inverse,
point_count, point_offset, x, y, z );
/*
@@ -88,14 +88,16 @@ int pj_apply_gridshift_2( PJ *defn, int inverse,
if( defn->gridlist == NULL )
{
defn->gridlist =
- pj_gridlist_from_nadgrids( pj_param(defn->params,"snadgrids").s,
+ pj_gridlist_from_nadgrids( pj_get_ctx( defn ),
+ pj_param(defn->params,"snadgrids").s,
&(defn->gridlist_count) );
if( defn->gridlist == NULL || defn->gridlist_count == 0 )
- return pj_errno;
+ return defn->ctx->last_errno;
}
- return pj_apply_gridshift_3( defn->gridlist, defn->gridlist_count, inverse,
+ return pj_apply_gridshift_3( pj_get_ctx( defn ),
+ defn->gridlist, defn->gridlist_count, inverse,
point_count, point_offset, x, y, z );
}
@@ -106,22 +108,21 @@ int pj_apply_gridshift_2( PJ *defn, int inverse,
/* This is the real workhorse, given a gridlist. */
/************************************************************************/
-int pj_apply_gridshift_3( PJ_GRIDINFO **tables, int grid_count,
+int pj_apply_gridshift_3( projCtx ctx, PJ_GRIDINFO **tables, int grid_count,
int inverse, long point_count, int point_offset,
double *x, double *y, double *z )
{
int i;
- int debug_flag = getenv( "PROJ_DEBUG" ) != NULL;
static int debug_count = 0;
if( tables == NULL || grid_count == 0 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38);
return -38;
}
- pj_errno = 0;
+ ctx->last_errno = 0;
for( i = 0; i < point_count; i++ )
{
@@ -172,44 +173,44 @@ int pj_apply_gridshift_3( PJ_GRIDINFO **tables, int grid_count,
}
/* load the grid shift info if we don't have it. */
- if( ct->cvs == NULL && !pj_gridinfo_load( gi ) )
+ if( ct->cvs == NULL && !pj_gridinfo_load( ctx, gi ) )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return -38;
}
output = nad_cvt( input, inverse, ct );
if( output.lam != HUGE_VAL )
{
- if( debug_flag && debug_count++ < 20 )
- fprintf( stderr,
- "pj_apply_gridshift(): used %s\n",
- ct->id );
+ if( debug_count++ < 20 )
+ pj_log( ctx, PJ_LOG_DEBUG_MINOR,
+ "pj_apply_gridshift(): used %s", ct->id );
break;
}
}
if( output.lam == HUGE_VAL )
{
- if( debug_flag )
+ if( ctx->debug_level >= PJ_LOG_DEBUG_MAJOR )
{
- fprintf( stderr,
- "pj_apply_gridshift(): failed to find a grid shift table for\n"
- " location (%.7fdW,%.7fdN)\n",
- x[io] * RAD_TO_DEG,
- y[io] * RAD_TO_DEG );
+ pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
+ "pj_apply_gridshift(): failed to find a grid shift table for\n"
+ " location (%.7fdW,%.7fdN)",
+ x[io] * RAD_TO_DEG,
+ y[io] * RAD_TO_DEG );
for( itable = 0; itable < grid_count; itable++ )
{
PJ_GRIDINFO *gi = tables[itable];
if( itable == 0 )
- fprintf( stderr, " tried: %s", gi->gridname );
+ pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
+ " tried: %s", gi->gridname );
else
- fprintf( stderr, ",%s", gi->gridname );
+ pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
+ ",%s", gi->gridname );
}
- fprintf( stderr, "\n" );
}
- pj_errno = PJD_ERR_GRID_AREA;
+ pj_ctx_set_errno( ctx, PJD_ERR_GRID_AREA );
return PJD_ERR_GRID_AREA;
}
else
diff --git a/src/pj_apply_vgridshift.c b/src/pj_apply_vgridshift.c
index 7696ea19..2d514587 100644
--- a/src/pj_apply_vgridshift.c
+++ b/src/pj_apply_vgridshift.c
@@ -59,21 +59,22 @@ int pj_apply_vgridshift( PJ *defn, const char *listname,
if( *gridlist_p == NULL )
{
*gridlist_p =
- pj_gridlist_from_nadgrids( pj_param(defn->params,listname).s,
+ pj_gridlist_from_nadgrids( pj_get_ctx(defn),
+ pj_param(defn->params,listname).s,
gridlist_count_p );
if( *gridlist_p == NULL || *gridlist_count_p == 0 )
- return pj_errno;
+ return defn->ctx->last_errno;
}
if( tables == NULL || *gridlist_count_p == 0 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( defn->ctx, -38);
return -38;
}
tables = *gridlist_p;
- pj_errno = 0;
+ defn->ctx->last_errno = 0;
for( i = 0; i < point_count; i++ )
{
@@ -126,9 +127,9 @@ int pj_apply_vgridshift( PJ *defn, const char *listname,
}
/* load the grid shift info if we don't have it. */
- if( ct->cvs == NULL && !pj_gridinfo_load( gi ) )
+ if( ct->cvs == NULL && !pj_gridinfo_load( pj_get_ctx(defn), gi ) )
{
- pj_errno = -38;
+ pj_ctx_set_errno( defn->ctx, -38 );
return -38;
}
@@ -190,7 +191,7 @@ int pj_apply_vgridshift( PJ *defn, const char *listname,
fprintf( stderr, "\n" );
}
- pj_errno = PJD_ERR_GRID_AREA;
+ pj_ctx_set_errno( defn->ctx, PJD_ERR_GRID_AREA );
return PJD_ERR_GRID_AREA;
}
}
diff --git a/src/pj_ctx.c b/src/pj_ctx.c
new file mode 100644
index 00000000..a9dc7ab8
--- /dev/null
+++ b/src/pj_ctx.c
@@ -0,0 +1,179 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project: PROJ.4
+ * Purpose: Implementation of the projCtx thread context object.
+ * Author: Frank Warmerdam, warmerdam@pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Frank Warmerdam
+ *
+ * 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>
+#include <string.h>
+
+PJ_CVSID("$Id$");
+
+static projCtx_t default_context;
+static int default_context_initialized = 0;
+
+/************************************************************************/
+/* pj_get_ctx() */
+/************************************************************************/
+
+projCtx pj_get_ctx( projPJ pj )
+
+{
+ return pj->ctx;
+}
+
+/************************************************************************/
+/* pj_set_ctx() */
+/* */
+/* Note we do not deallocate the old context! */
+/************************************************************************/
+
+void pj_set_ctx( projPJ pj, projCtx ctx )
+
+{
+ pj->ctx = ctx;
+}
+
+/************************************************************************/
+/* pj_get_default_ctx() */
+/************************************************************************/
+
+projCtx pj_get_default_ctx()
+
+{
+ pj_acquire_lock();
+
+ if( !default_context_initialized )
+ {
+ default_context_initialized = 1;
+ default_context.last_errno = 0;
+ default_context.debug_level = PJ_LOG_NONE;
+ default_context.logger = pj_stderr_logger;
+ default_context.app_data = NULL;
+
+ if( getenv("PROJ_DEBUG") != NULL )
+ {
+ if( atoi(getenv("PROJ_DEBUG")) > 0 )
+ default_context.debug_level = atoi(getenv("PROJ_DEBUG"));
+ else
+ default_context.debug_level = PJ_LOG_DEBUG_MINOR;
+ }
+ }
+
+ pj_release_lock();
+
+ return &default_context;
+}
+
+/************************************************************************/
+/* pj_ctx_alloc() */
+/************************************************************************/
+
+projCtx pj_ctx_alloc()
+
+{
+ projCtx ctx = (projCtx_t *) malloc(sizeof(projCtx_t));
+ memcpy( ctx, pj_get_default_ctx(), sizeof(projCtx_t) );
+ ctx->last_errno = 0;
+
+ return ctx;
+}
+
+/************************************************************************/
+/* pj_ctx_free() */
+/************************************************************************/
+
+void pj_ctx_free( projCtx ctx )
+
+{
+ free( ctx );
+}
+
+/************************************************************************/
+/* pj_ctx_get_errno() */
+/************************************************************************/
+
+int pj_ctx_get_errno( projCtx ctx )
+
+{
+ return ctx->last_errno;
+}
+
+/************************************************************************/
+/* pj_ctx_set_errno() */
+/* */
+/* Also sets the global errno. */
+/************************************************************************/
+
+void pj_ctx_set_errno( projCtx ctx, int new_errno )
+
+{
+ ctx->last_errno = new_errno;
+ if( new_errno != 0 )
+ pj_errno = new_errno;
+}
+
+/************************************************************************/
+/* pj_ctx_set_debug() */
+/************************************************************************/
+
+void pj_ctx_set_debug( projCtx ctx, int new_debug )
+
+{
+ ctx->debug_level = new_debug;
+}
+
+/************************************************************************/
+/* pj_ctx_set_logger() */
+/************************************************************************/
+
+void pj_ctx_set_logger( projCtx ctx, void (*new_logger)(void*,int,const char*) )
+
+{
+ ctx->logger = new_logger;
+}
+
+/************************************************************************/
+/* pj_ctx_set_app_data() */
+/************************************************************************/
+
+void pj_ctx_set_app_data( projCtx ctx, void *new_app_data )
+
+{
+ ctx->app_data = new_app_data;
+}
+
+/************************************************************************/
+/* pj_ctx_get_app_data() */
+/************************************************************************/
+
+void *pj_ctx_get_app_data( projCtx ctx )
+
+{
+ return ctx->app_data;
+}
+
+
diff --git a/src/pj_datum_set.c b/src/pj_datum_set.c
index 8ca8fc46..37df66b2 100644
--- a/src/pj_datum_set.c
+++ b/src/pj_datum_set.c
@@ -37,7 +37,7 @@
/* pj_datum_set() */
/************************************************************************/
-int pj_datum_set(paralist *pl, PJ *projdef)
+int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef)
{
const char *name, *towgs84, *nadgrids;
@@ -66,7 +66,7 @@ int pj_datum_set(paralist *pl, PJ *projdef)
/* find the datum definition */
for (i = 0; (s = pj_datums[i].id) && strcmp(name, s) ; ++i) {}
- if (!s) { pj_errno = -9; return 1; }
+ if (!s) { pj_ctx_set_errno(ctx, -9); return 1; }
if( pj_datums[i].ellipse_id && strlen(pj_datums[i].ellipse_id) > 0 )
{
diff --git a/src/pj_ell_set.c b/src/pj_ell_set.c
index 56cabd4c..c0d139d7 100644
--- a/src/pj_ell_set.c
+++ b/src/pj_ell_set.c
@@ -7,7 +7,7 @@
#define RV4 .06944444444444444444 /* 5/72 */
#define RV6 .04243827160493827160 /* 55/1296 */
int /* initialize geographic shape parameters */
-pj_ell_set(paralist *pl, double *a, double *es) {
+pj_ell_set(projCtx ctx, paralist *pl, double *a, double *es) {
int i;
double b=0.0, e;
char *name;
@@ -27,7 +27,7 @@ pj_ell_set(paralist *pl, double *a, double *es) {
for (start = pl; start && start->next ; start = start->next) ;
curr = start;
for (i = 0; (s = pj_ellps[i].id) && strcmp(name, s) ; ++i) ;
- if (!s) { pj_errno = -9; return 1; }
+ if (!s) { pj_ctx_set_errno( ctx, -9); return 1; }
curr = curr->next = pj_mkparam(pj_ellps[i].major);
curr = curr->next = pj_mkparam(pj_ellps[i].ell);
}
@@ -40,7 +40,7 @@ pj_ell_set(paralist *pl, double *a, double *es) {
} else if (pj_param(pl, "trf").i) { /* recip flattening */
*es = pj_param(pl, "drf").f;
if (!*es) {
- pj_errno = -10;
+ pj_ctx_set_errno( ctx, -10);
goto bomb;
}
*es = 1./ *es;
@@ -76,7 +76,7 @@ pj_ell_set(paralist *pl, double *a, double *es) {
tmp = sin(pj_param(pl, i ? "rR_lat_a" : "rR_lat_g").f);
if (fabs(tmp) > HALFPI) {
- pj_errno = -11;
+ pj_ctx_set_errno(ctx,-11);
goto bomb;
}
tmp = 1. - *es * tmp * tmp;
@@ -90,13 +90,13 @@ bomb:
pj_dalloc(start->next);
start->next = 0;
}
- if (pj_errno)
+ if (ctx->last_errno)
return 1;
}
/* some remaining checks */
if (*es < 0.)
- { pj_errno = -12; return 1; }
+ { pj_ctx_set_errno( ctx, -12); return 1; }
if (*a <= 0.)
- { pj_errno = -13; return 1; }
+ { pj_ctx_set_errno( ctx, -13); return 1; }
return 0;
}
diff --git a/src/pj_factors.c b/src/pj_factors.c
index ee48cfb7..2c478a81 100644
--- a/src/pj_factors.c
+++ b/src/pj_factors.c
@@ -13,10 +13,12 @@ pj_factors(LP lp, PJ *P, double h, struct FACTORS *fac) {
/* check for forward and latitude or longitude overange */
if ((t = fabs(lp.phi)-HALFPI) > EPS || fabs(lp.lam) > 10.) {
- pj_errno = -14;
+ pj_ctx_set_errno( P->ctx->last_errno, -14);
return 1;
} else { /* proceed */
errno = pj_errno = 0;
+ P->ctx->last_errno = 0;
+
if (h < EPS)
h = DEFAULT_H;
if (fabs(lp.phi) > (HALFPI - h))
diff --git a/src/pj_fwd.c b/src/pj_fwd.c
index 880a9319..b70b4240 100644
--- a/src/pj_fwd.c
+++ b/src/pj_fwd.c
@@ -11,9 +11,12 @@ pj_fwd(LP lp, PJ *P) {
/* check for forward and latitude or longitude overange */
if ((t = fabs(lp.phi)-HALFPI) > EPS || fabs(lp.lam) > 10.) {
xy.x = xy.y = HUGE_VAL;
- pj_errno = -14;
+ pj_ctx_set_errno( P->ctx, -14);
} else { /* proceed with projection */
- errno = pj_errno = 0;
+ P->ctx->last_errno = 0;
+ pj_errno = 0;
+ errno = 0;
+
if (fabs(t) <= EPS)
lp.phi = lp.phi < 0. ? -HALFPI : HALFPI;
else if (P->geoc)
@@ -22,7 +25,7 @@ pj_fwd(LP lp, PJ *P) {
if (!P->over)
lp.lam = adjlon(lp.lam); /* adjust del longitude */
xy = (*P->fwd)(lp, P); /* project */
- if (pj_errno || (pj_errno = errno))
+ if ( P->ctx->last_errno )
xy.x = xy.y = HUGE_VAL;
/* adjust for major axis and easting/northings */
else {
diff --git a/src/pj_gridinfo.c b/src/pj_gridinfo.c
index 8dcde5ee..e543d028 100644
--- a/src/pj_gridinfo.c
+++ b/src/pj_gridinfo.c
@@ -80,7 +80,7 @@ static void swap_words( unsigned char *data, int word_size, int word_count )
/* pj_gridinfo_free() */
/************************************************************************/
-void pj_gridinfo_free( PJ_GRIDINFO *gi )
+void pj_gridinfo_free( projCtx ctx, PJ_GRIDINFO *gi )
{
if( gi == NULL )
@@ -93,7 +93,7 @@ void pj_gridinfo_free( PJ_GRIDINFO *gi )
for( child = gi->child; child != NULL; child=next)
{
next=child->next;
- pj_gridinfo_free( child );
+ pj_gridinfo_free( ctx, child );
}
}
@@ -115,7 +115,7 @@ void pj_gridinfo_free( PJ_GRIDINFO *gi )
/* stuff are loaded by pj_gridinfo_init(). */
/************************************************************************/
-int pj_gridinfo_load( PJ_GRIDINFO *gi )
+int pj_gridinfo_load( projCtx ctx, PJ_GRIDINFO *gi )
{
if( gi == NULL || gi->ct == NULL )
@@ -130,15 +130,15 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
FILE *fid;
int result;
- fid = pj_open_lib( gi->filename, "rb" );
+ fid = pj_open_lib( ctx, gi->filename, "rb" );
if( fid == NULL )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
- result = nad_ctable_load( gi->ct, fid );
+ result = nad_ctable_load( ctx, gi->ct, fid );
fclose( fid );
@@ -158,11 +158,11 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
int row;
FILE *fid;
- fid = pj_open_lib( gi->filename, "rb" );
+ fid = pj_open_lib( ctx, gi->filename, "rb" );
if( fid == NULL )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -172,7 +172,7 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
gi->ct->cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP));
if( row_buf == NULL || gi->ct->cvs == NULL )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -187,7 +187,7 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
{
pj_dalloc( row_buf );
pj_dalloc( gi->ct->cvs );
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -232,11 +232,11 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
fprintf( stderr, "NTv2 - loading grid %s\n", gi->ct->id );
}
- fid = pj_open_lib( gi->filename, "rb" );
+ fid = pj_open_lib( ctx, gi->filename, "rb" );
if( fid == NULL )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -246,7 +246,7 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
gi->ct->cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP));
if( row_buf == NULL || gi->ct->cvs == NULL )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -262,7 +262,7 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
pj_dalloc( row_buf );
pj_dalloc( gi->ct->cvs );
gi->ct->cvs = NULL;
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -299,11 +299,11 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
int words = gi->ct->lim.lam * gi->ct->lim.phi;
FILE *fid;
- fid = pj_open_lib( gi->filename, "rb" );
+ fid = pj_open_lib( ctx, gi->filename, "rb" );
if( fid == NULL )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -312,7 +312,7 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
gi->ct->cvs = (FLP *) pj_malloc(words*sizeof(float));
if( gi->ct->cvs == NULL )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -320,7 +320,6 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
{
pj_dalloc( gi->ct->cvs );
gi->ct->cvs = NULL;
- pj_errno = -38;
return 0;
}
@@ -343,7 +342,7 @@ int pj_gridinfo_load( PJ_GRIDINFO *gi )
/* Load a ntv2 (.gsb) file. */
/************************************************************************/
-static int pj_gridinfo_init_ntv2( FILE *fid, PJ_GRIDINFO *gilist )
+static int pj_gridinfo_init_ntv2( projCtx ctx, FILE *fid, PJ_GRIDINFO *gilist )
{
unsigned char header[11*16];
@@ -355,7 +354,7 @@ static int pj_gridinfo_init_ntv2( FILE *fid, PJ_GRIDINFO *gilist )
{
fprintf( stderr,
"basic types of inappropraiate size in pj_gridinfo_init_ntv2()\n" );
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -364,7 +363,7 @@ static int pj_gridinfo_init_ntv2( FILE *fid, PJ_GRIDINFO *gilist )
/* -------------------------------------------------------------------- */
if( fread( header, sizeof(header), 1, fid ) != 1 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -402,13 +401,13 @@ static int pj_gridinfo_init_ntv2( FILE *fid, PJ_GRIDINFO *gilist )
/* -------------------------------------------------------------------- */
if( fread( header, sizeof(header), 1, fid ) != 1 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
if( strncmp((const char *) header,"SUB_NAME",8) != 0 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -465,7 +464,7 @@ static int pj_gridinfo_init_ntv2( FILE *fid, PJ_GRIDINFO *gilist )
"GS_COUNT(%d) does not match expected cells (%dx%d=%d)\n",
gs_count, ct->lim.lam, ct->lim.phi,
ct->lim.lam * ct->lim.phi );
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -550,7 +549,7 @@ static int pj_gridinfo_init_ntv2( FILE *fid, PJ_GRIDINFO *gilist )
/* Load an NTv1 style Canadian grid shift file. */
/************************************************************************/
-static int pj_gridinfo_init_ntv1( FILE * fid, PJ_GRIDINFO *gi )
+static int pj_gridinfo_init_ntv1( projCtx ctx, FILE * fid, PJ_GRIDINFO *gi )
{
unsigned char header[176];
@@ -563,7 +562,7 @@ static int pj_gridinfo_init_ntv1( FILE * fid, PJ_GRIDINFO *gi )
{
fprintf( stderr,
"basic types of inappropraiate size in nad_load_ntv1()\n" );
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -572,7 +571,7 @@ static int pj_gridinfo_init_ntv1( FILE * fid, PJ_GRIDINFO *gi )
/* -------------------------------------------------------------------- */
if( fread( header, sizeof(header), 1, fid ) != 1 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -592,7 +591,7 @@ static int pj_gridinfo_init_ntv1( FILE * fid, PJ_GRIDINFO *gi )
if( *((int *) (header+8)) != 12 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
printf("NTv1 grid shift file has wrong record count, corrupt?\n");
return 0;
}
@@ -637,7 +636,7 @@ static int pj_gridinfo_init_ntv1( FILE * fid, PJ_GRIDINFO *gi )
/* Load a NOAA .gtx vertical datum shift file. */
/************************************************************************/
-static int pj_gridinfo_init_gtx( FILE * fid, PJ_GRIDINFO *gi )
+static int pj_gridinfo_init_gtx( projCtx ctx, FILE * fid, PJ_GRIDINFO *gi )
{
unsigned char header[40];
@@ -651,7 +650,7 @@ static int pj_gridinfo_init_gtx( FILE * fid, PJ_GRIDINFO *gi )
{
fprintf( stderr,
"basic types of inappropraiate size in nad_load_gtx()\n" );
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -660,7 +659,7 @@ static int pj_gridinfo_init_gtx( FILE * fid, PJ_GRIDINFO *gi )
/* -------------------------------------------------------------------- */
if( fread( header, sizeof(header), 1, fid ) != 1 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return 0;
}
@@ -684,7 +683,7 @@ static int pj_gridinfo_init_gtx( FILE * fid, PJ_GRIDINFO *gi )
if( xorigin < -360 || xorigin > 360
|| yorigin < -90 || yorigin > 90 )
{
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
printf("gtx file header has invalid extents, corrupt?\n");
return 0;
}
@@ -731,7 +730,7 @@ static int pj_gridinfo_init_gtx( FILE * fid, PJ_GRIDINFO *gi )
/* applications. */
/************************************************************************/
-PJ_GRIDINFO *pj_gridinfo_init( const char *gridname )
+PJ_GRIDINFO *pj_gridinfo_init( projCtx ctx, const char *gridname )
{
char fname[MAX_PATH_FILENAME+1];
@@ -740,6 +739,7 @@ PJ_GRIDINFO *pj_gridinfo_init( const char *gridname )
char header[160];
errno = pj_errno = 0;
+ ctx->last_errno = 0;
/* -------------------------------------------------------------------- */
/* Initialize a GRIDINFO with stub info we would use if it */
@@ -759,7 +759,7 @@ PJ_GRIDINFO *pj_gridinfo_init( const char *gridname )
/* Open the file using the usual search rules. */
/* -------------------------------------------------------------------- */
strcpy(fname, gridname);
- if (!(fp = pj_open_lib(fname, "rb"))) {
+ if (!(fp = pj_open_lib(ctx, fname, "rb"))) {
pj_errno = errno;
return gilist;
}
@@ -772,7 +772,7 @@ PJ_GRIDINFO *pj_gridinfo_init( const char *gridname )
if( fread( header, sizeof(header), 1, fp ) != 1 )
{
fclose( fp );
- pj_errno = -38;
+ pj_ctx_set_errno( ctx, -38 );
return gilist;
}
@@ -785,37 +785,36 @@ PJ_GRIDINFO *pj_gridinfo_init( const char *gridname )
&& strncmp(header + 96, "W GRID", 6) == 0
&& strncmp(header + 144, "TO NAD83 ", 16) == 0 )
{
- pj_gridinfo_init_ntv1( fp, gilist );
+ pj_gridinfo_init_ntv1( ctx, fp, gilist );
}
else if( strncmp(header + 0, "NUM_OREC", 8) == 0
&& strncmp(header + 48, "GS_TYPE", 7) == 0 )
{
- pj_gridinfo_init_ntv2( fp, gilist );
+ pj_gridinfo_init_ntv2( ctx, fp, gilist );
}
else if( strlen(gridname) > 4
&& (strcmp(gridname+strlen(gridname)-3,"gtx") == 0
|| strcmp(gridname+strlen(gridname)-3,"GTX") == 0) )
{
- pj_gridinfo_init_gtx( fp, gilist );
+ pj_gridinfo_init_gtx( ctx, fp, gilist );
}
else
{
- struct CTABLE *ct = nad_ctable_init( fp );
+ struct CTABLE *ct = nad_ctable_init( ctx, fp );
gilist->format = "ctable";
gilist->ct = ct;
- if( getenv("PROJ_DEBUG") != NULL )
- fprintf( stderr,
- "Ctable %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
- ct->id,
- ct->lim.lam, ct->lim.phi,
- ct->ll.lam * RAD_TO_DEG, ct->ll.phi * RAD_TO_DEG,
- (ct->ll.lam + (ct->lim.lam-1)*ct->del.lam) * RAD_TO_DEG,
- (ct->ll.phi + (ct->lim.phi-1)*ct->del.phi) * RAD_TO_DEG );
+ pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
+ "Ctable %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
+ ct->id,
+ ct->lim.lam, ct->lim.phi,
+ ct->ll.lam * RAD_TO_DEG, ct->ll.phi * RAD_TO_DEG,
+ (ct->ll.lam + (ct->lim.lam-1)*ct->del.lam) * RAD_TO_DEG,
+ (ct->ll.phi + (ct->lim.phi-1)*ct->del.phi) * RAD_TO_DEG );
}
fclose(fp);
diff --git a/src/pj_gridlist.c b/src/pj_gridlist.c
index 52b44e42..3277bb5c 100644
--- a/src/pj_gridlist.c
+++ b/src/pj_gridlist.c
@@ -61,7 +61,7 @@ void pj_deallocate_grids()
grid_list = grid_list->next;
item->next = NULL;
- pj_gridinfo_free( item );
+ pj_gridinfo_free( pj_get_default_ctx(), item );
}
}
@@ -72,7 +72,8 @@ void pj_deallocate_grids()
/* last_nadgrids_list. */
/************************************************************************/
-static int pj_gridlist_merge_gridfile( const char *gridname,
+static int pj_gridlist_merge_gridfile( projCtx ctx,
+ const char *gridname,
PJ_GRIDINFO ***p_gridlist,
int *p_gridcount,
int *p_gridmax )
@@ -128,7 +129,7 @@ static int pj_gridlist_merge_gridfile( const char *gridname,
/* -------------------------------------------------------------------- */
/* Try to load the named grid. */
/* -------------------------------------------------------------------- */
- this_grid = pj_gridinfo_init( gridname );
+ this_grid = pj_gridinfo_init( ctx, gridname );
if( this_grid == NULL )
{
@@ -145,7 +146,7 @@ static int pj_gridlist_merge_gridfile( const char *gridname,
/* -------------------------------------------------------------------- */
/* Recurse to add the grid now that it is loaded. */
/* -------------------------------------------------------------------- */
- return pj_gridlist_merge_gridfile( gridname, p_gridlist,
+ return pj_gridlist_merge_gridfile( ctx, gridname, p_gridlist,
p_gridcount, p_gridmax );
}
@@ -159,7 +160,8 @@ static int pj_gridlist_merge_gridfile( const char *gridname,
/* the cost of building the list of tables each time. */
/************************************************************************/
-PJ_GRIDINFO **pj_gridlist_from_nadgrids( const char *nadgrids, int *grid_count)
+PJ_GRIDINFO **pj_gridlist_from_nadgrids( projCtx ctx, const char *nadgrids,
+ int *grid_count)
{
const char *s;
@@ -204,7 +206,7 @@ PJ_GRIDINFO **pj_gridlist_from_nadgrids( const char *nadgrids, int *grid_count)
if( *s == ',' )
s++;
- if( !pj_gridlist_merge_gridfile( name, &gridlist, grid_count,
+ if( !pj_gridlist_merge_gridfile( ctx, name, &gridlist, grid_count,
&grid_max)
&& required )
{
diff --git a/src/pj_init.c b/src/pj_init.c
index 17141b0f..073807d6 100644
--- a/src/pj_init.c
+++ b/src/pj_init.c
@@ -38,8 +38,6 @@
PJ_CVSID("$Id$");
-extern FILE *pj_open_lib(char *, char *);
-
/************************************************************************/
/* get_opt() */
/************************************************************************/
@@ -86,10 +84,10 @@ get_opt(paralist **start, FILE *fid, char *name, paralist *next) {
/* get_defaults() */
/************************************************************************/
static paralist *
-get_defaults(paralist **start, paralist *next, char *name) {
+get_defaults(projCtx ctx, paralist **start, paralist *next, char *name) {
FILE *fid;
- if ( (fid = pj_open_lib("proj_def.dat", "rt")) != NULL) {
+ if ( (fid = pj_open_lib(ctx,"proj_def.dat", "rt")) != NULL) {
next = get_opt(start, fid, "general", next);
rewind(fid);
next = get_opt(start, fid, name, next);
@@ -104,7 +102,7 @@ get_defaults(paralist **start, paralist *next, char *name) {
/* get_init() */
/************************************************************************/
static paralist *
-get_init(paralist **start, paralist *next, char *name) {
+get_init(projCtx ctx, paralist **start, paralist *next, char *name) {
char fname[MAX_PATH_FILENAME+ID_TAG_MAX+3], *opt;
FILE *fid;
paralist *init_items = NULL;
@@ -130,11 +128,12 @@ get_init(paralist **start, paralist *next, char *name) {
*/
if ((opt = strrchr(fname, ':')) != NULL)
*opt++ = '\0';
- else { pj_errno = -3; return(0); }
- if ( (fid = pj_open_lib(fname, "rt")) != NULL)
+ else { pj_ctx_set_errno(ctx,-3); return NULL; }
+
+ if ( (fid = pj_open_lib(ctx,fname, "rt")) != NULL)
next = get_opt(start, fid, opt, next);
else
- return(0);
+ return NULL;
(void)fclose(fid);
if (errno == 25)
errno = 0; /* unknown problem with some sys errno<-25 */
@@ -161,11 +160,17 @@ PJ *
pj_init_plus( const char *definition )
{
+ return pj_init_plus_ctx( pj_get_default_ctx(), definition );
+}
+
+PJ *
+pj_init_plus_ctx( projCtx ctx, const char *definition )
+{
#define MAX_ARG 200
char *argv[MAX_ARG];
char *defn_copy;
int argc = 0, i;
- PJ *result;
+ PJ *result;
/* make a copy that we can manipulate */
defn_copy = (char *) pj_malloc( strlen(definition)+1 );
@@ -182,7 +187,7 @@ pj_init_plus( const char *definition )
{
if( argc+1 == MAX_ARG )
{
- pj_errno = -44;
+ pj_ctx_set_errno( ctx, -44 );
return NULL;
}
@@ -202,7 +207,7 @@ pj_init_plus( const char *definition )
}
/* perform actual initialization */
- result = pj_init( argc, argv );
+ result = pj_init_ctx( ctx, argc, argv );
pj_dalloc( defn_copy );
@@ -220,6 +225,11 @@ pj_init_plus( const char *definition )
PJ *
pj_init(int argc, char **argv) {
+ return pj_init_ctx( pj_get_default_ctx(), argc, argv );
+}
+
+PJ *
+pj_init_ctx(projCtx ctx, int argc, char **argv) {
char *s, *name;
paralist *start = NULL;
PJ *(*proj)(PJ *);
@@ -228,43 +238,44 @@ pj_init(int argc, char **argv) {
PJ *PIN = 0;
const char *old_locale;
- errno = pj_errno = 0;
+ ctx->last_errno = 0;
start = NULL;
old_locale = setlocale(LC_NUMERIC, NULL);
setlocale(LC_NUMERIC,"C");
/* put arguments into internal linked list */
- if (argc <= 0) { pj_errno = -1; goto bum_call; }
+ if (argc <= 0) { pj_ctx_set_errno( ctx, -1 ); goto bum_call; }
for (i = 0; i < argc; ++i)
if (i)
curr = curr->next = pj_mkparam(argv[i]);
else
start = curr = pj_mkparam(argv[i]);
- if (pj_errno) goto bum_call;
+ if (ctx->last_errno) goto bum_call;
/* check if +init present */
if (pj_param(start, "tinit").i) {
paralist *last = curr;
- if (!(curr = get_init(&start, curr, pj_param(start, "sinit").s)))
+ if (!(curr = get_init(ctx,&start, curr, pj_param(start, "sinit").s)))
goto bum_call;
- if (curr == last) { pj_errno = -2; goto bum_call; }
+ if (curr == last) { pj_ctx_set_errno( ctx, -2); goto bum_call; }
}
/* find projection selection */
if (!(name = pj_param(start, "sproj").s))
- { pj_errno = -4; goto bum_call; }
+ { pj_ctx_set_errno( ctx, -4 ); goto bum_call; }
for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ;
- if (!s) { pj_errno = -5; goto bum_call; }
+ if (!s) { pj_ctx_set_errno( ctx, -5 ); goto bum_call; }
/* set defaults, unless inhibited */
if (!pj_param(start, "bno_defs").i)
- curr = get_defaults(&start, curr, name);
+ curr = get_defaults(ctx,&start, curr, name);
proj = (PJ *(*)(PJ *)) pj_list[i].proj;
/* allocate projection structure */
if (!(PIN = (*proj)(0))) goto bum_call;
+ PIN->ctx = ctx;
PIN->params = start;
PIN->is_latlong = 0;
PIN->is_geocent = 0;
@@ -279,10 +290,10 @@ pj_init(int argc, char **argv) {
PIN->vgridlist_geoid_count = 0;
/* set datum parameters */
- if (pj_datum_set(start, PIN)) goto bum_call;
+ if (pj_datum_set(ctx, start, PIN)) goto bum_call;
/* set ellipsoid/sphere parameters */
- if (pj_ell_set(start, &PIN->a, &PIN->es)) goto bum_call;
+ if (pj_ell_set(ctx, start, &PIN->a, &PIN->es)) goto bum_call;
PIN->a_orig = PIN->a;
PIN->es_orig = PIN->es;
@@ -290,7 +301,7 @@ pj_init(int argc, char **argv) {
PIN->e = sqrt(PIN->es);
PIN->ra = 1. / PIN->a;
PIN->one_es = 1. - PIN->es;
- if (PIN->one_es == 0.) { pj_errno = -6; goto bum_call; }
+ if (PIN->one_es == 0.) { pj_ctx_set_errno( ctx, -6 ); goto bum_call; }
PIN->rone_es = 1./PIN->one_es;
/* Now that we have ellipse information check for WGS84 datum */
@@ -325,7 +336,7 @@ pj_init(int argc, char **argv) {
const char *axis_arg = pj_param(start,"saxis").s;
if( strlen(axis_arg) != 3 )
{
- pj_errno = PJD_ERR_AXIS;
+ pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
goto bum_call;
}
@@ -333,7 +344,7 @@ pj_init(int argc, char **argv) {
|| strchr( axis_legal, axis_arg[1] ) == NULL
|| (axis_arg[2] && strchr( axis_legal, axis_arg[1] ) == NULL))
{
- pj_errno = PJD_ERR_AXIS;
+ pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
goto bum_call;
}
@@ -363,7 +374,7 @@ pj_init(int argc, char **argv) {
else
PIN->k0 = 1.;
if (PIN->k0 <= 0.) {
- pj_errno = -31;
+ pj_ctx_set_errno( ctx, -31 );
goto bum_call;
}
@@ -371,7 +382,7 @@ pj_init(int argc, char **argv) {
s = 0;
if ((name = pj_param(start, "sunits").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
- if (!s) { pj_errno = -7; goto bum_call; }
+ if (!s) { pj_ctx_set_errno( ctx, -7 ); goto bum_call; }
s = pj_units[i].to_meter;
}
if (s || (s = pj_param(start, "sto_meter").s)) {
@@ -402,17 +413,15 @@ pj_init(int argc, char **argv) {
&& *next_str == '\0' )
value = name;
- if (!value) { pj_errno = -46; goto bum_call; }
+ if (!value) { pj_ctx_set_errno( ctx, -46 ); goto bum_call; }
PIN->from_greenwich = dmstor(value,NULL);
}
else
PIN->from_greenwich = 0.0;
/* projection specific initialization */
- if (!(PIN = (*proj)(PIN)) || errno || pj_errno) {
+ if (!(PIN = (*proj)(PIN)) || ctx->last_errno) {
bum_call: /* cleanup error return */
- if (!pj_errno)
- pj_errno = errno;
if (PIN)
pj_free(PIN);
else
@@ -451,7 +460,7 @@ pj_free(PJ *P) {
/* free array of grid pointers if we have one */
if( P->gridlist != NULL )
pj_dalloc( P->gridlist );
-
+
/* free projection parameters */
P->pfree(P);
}
diff --git a/src/pj_inv.c b/src/pj_inv.c
index ee2b44f8..a418ccd4 100644
--- a/src/pj_inv.c
+++ b/src/pj_inv.c
@@ -10,13 +10,17 @@ pj_inv(XY xy, PJ *P) {
/* can't do as much preliminary checking as with forward */
if (xy.x == HUGE_VAL || xy.y == HUGE_VAL) {
lp.lam = lp.phi = HUGE_VAL;
- pj_errno = -15;
+ pj_ctx_set_errno( P->ctx, -15);
+ return lp;
}
+
errno = pj_errno = 0;
+ P->ctx->last_errno = 0;
+
xy.x = (xy.x * P->to_meter - P->x0) * P->ra; /* descale and de-offset */
xy.y = (xy.y * P->to_meter - P->y0) * P->ra;
lp = (*P->inv)(xy, P); /* inverse project */
- if (pj_errno || (pj_errno = errno))
+ if (P->ctx->last_errno )
lp.lam = lp.phi = HUGE_VAL;
else {
lp.lam += P->lam0; /* reduce from del lp.lam */
diff --git a/src/pj_log.c b/src/pj_log.c
new file mode 100644
index 00000000..630a3cfe
--- /dev/null
+++ b/src/pj_log.c
@@ -0,0 +1,73 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project: PROJ.4
+ * Purpose: Implementation of pj_log() function.
+ * Author: Frank Warmerdam, warmerdam@pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Frank Warmerdam
+ *
+ * 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>
+#include <string.h>
+#include <stdarg.h>
+
+PJ_CVSID("$Id$");
+
+/************************************************************************/
+/* pj_stderr_logger() */
+/************************************************************************/
+
+void pj_stderr_logger( void *app_data, int level, const char *msg )
+
+{
+ fprintf( stderr, "%s\n", msg );
+}
+
+/************************************************************************/
+/* pj_log() */
+/************************************************************************/
+
+void pj_log( projCtx ctx, int level, const char *fmt, ... )
+
+{
+ va_list args;
+ char *msg_buf;
+
+ if( level > ctx->debug_level )
+ return;
+
+ msg_buf = (char *) malloc(100000);
+ if( msg_buf == NULL )
+ return;
+
+ va_start( args, fmt );
+
+ /* we should use vsnprintf where available once we add configure detect.*/
+ vsprintf( msg_buf, fmt, args );
+
+ va_end( args );
+
+ ctx->logger( ctx->app_data, level, msg_buf );
+
+ free( msg_buf );
+}
diff --git a/src/pj_open_lib.c b/src/pj_open_lib.c
index cb6aab30..b15cbdf6 100644
--- a/src/pj_open_lib.c
+++ b/src/pj_open_lib.c
@@ -99,7 +99,7 @@ void pj_set_searchpath ( int count, const char **path )
/************************************************************************/
FILE *
-pj_open_lib(char *name, char *mode) {
+pj_open_lib(projCtx ctx, char *name, char *mode) {
char fname[MAX_PATH_FILENAME+1];
const char *sysname;
FILE *fid;
@@ -161,10 +161,10 @@ pj_open_lib(char *name, char *mode) {
errno = 0;
}
- if( getenv( "PROJ_DEBUG" ) != NULL )
- fprintf( stderr, "pj_open_lib(%s): call fopen(%s) - %s\n",
- name, sysname,
- fid == NULL ? "failed" : "succeeded" );
+ pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
+ "pj_open_lib(%s): call fopen(%s) - %s\n",
+ name, sysname,
+ fid == NULL ? "failed" : "succeeded" );
return(fid);
#else
diff --git a/src/pj_transform.c b/src/pj_transform.c
index 33c1dcd1..60f6dd72 100644
--- a/src/pj_transform.c
+++ b/src/pj_transform.c
@@ -36,7 +36,7 @@
PJ_CVSID("$Id$");
-static int pj_adjust_axis( const char *axis, int denormalize_flag,
+static int pj_adjust_axis( projCtx ctx, const char *axis, int denormalize_flag,
long point_count, int point_offset,
double *x, double *y, double *z );
@@ -91,7 +91,8 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
long i;
int err;
- pj_errno = 0;
+ srcdefn->ctx->last_errno = 0;
+ dstdefn->ctx->last_errno = 0;
if( point_offset == 0 )
point_offset = 1;
@@ -104,8 +105,8 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
{
int err;
- err = pj_adjust_axis( srcdefn->axis, 0, point_count, point_offset,
- x, y, z );
+ err = pj_adjust_axis( srcdefn->ctx, srcdefn->axis,
+ 0, point_count, point_offset, x, y, z );
if( err != 0 )
return err;
}
@@ -117,7 +118,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
{
if( z == NULL )
{
- pj_errno = PJD_ERR_GEOCENTRIC;
+ pj_ctx_set_errno( pj_get_ctx(srcdefn), PJD_ERR_GEOCENTRIC);
return PJD_ERR_GEOCENTRIC;
}
@@ -148,12 +149,9 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
{
if( srcdefn->inv == NULL )
{
- pj_errno = -17; /* this isn't correct, we need a no inverse err */
- if( getenv( "PROJ_DEBUG" ) != NULL )
- {
- fprintf( stderr,
- "pj_transform(): source projection not invertable\n" );
- }
+ pj_ctx_set_errno( pj_get_ctx(srcdefn), -17 );
+ pj_log( pj_get_ctx(srcdefn), PJ_LOG_ERROR,
+ "pj_transform(): source projection not invertable" );
return -17;
}
@@ -169,12 +167,14 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
continue;
geodetic_loc = pj_inv( projected_loc, srcdefn );
- if( pj_errno != 0 )
+ if( srcdefn->ctx->last_errno != 0 )
{
- if( (pj_errno != 33 /*EDOM*/ && pj_errno != 34 /*ERANGE*/ )
- && (pj_errno > 0 || pj_errno < -44 || point_count == 1
- || transient_error[-pj_errno] == 0 ) )
- return pj_errno;
+ if( (srcdefn->ctx->last_errno != 33 /*EDOM*/
+ && srcdefn->ctx->last_errno != 34 /*ERANGE*/ )
+ && (srcdefn->ctx->last_errno > 0
+ || srcdefn->ctx->last_errno < -44 || point_count == 1
+ || transient_error[-srcdefn->ctx->last_errno] == 0 ) )
+ return srcdefn->ctx->last_errno;
else
{
geodetic_loc.u = HUGE_VAL;
@@ -209,7 +209,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
&(srcdefn->vgridlist_geoid),
&(srcdefn->vgridlist_geoid_count),
0, point_count, point_offset, x, y, z ) )
- return pj_errno;
+ return pj_ctx_get_errno(srcdefn->ctx);
}
/* -------------------------------------------------------------------- */
@@ -217,7 +217,12 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
/* -------------------------------------------------------------------- */
if( pj_datum_transform( srcdefn, dstdefn, point_count, point_offset,
x, y, z ) != 0 )
- return pj_errno;
+ {
+ if( srcdefn->ctx->last_errno != 0 )
+ return srcdefn->ctx->last_errno;
+ else
+ return dstdefn->ctx->last_errno;
+ }
/* -------------------------------------------------------------------- */
/* Do we need to translate from geoid to ellipsoidal vertical */
@@ -229,7 +234,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
&(dstdefn->vgridlist_geoid),
&(dstdefn->vgridlist_geoid_count),
0, point_count, point_offset, x, y, z ) )
- return pj_errno;
+ return dstdefn->ctx->last_errno;
}
/* -------------------------------------------------------------------- */
@@ -253,7 +258,7 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
{
if( z == NULL )
{
- pj_errno = PJD_ERR_GEOCENTRIC;
+ pj_ctx_set_errno( dstdefn->ctx, PJD_ERR_GEOCENTRIC );
return PJD_ERR_GEOCENTRIC;
}
@@ -291,12 +296,14 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
continue;
projected_loc = pj_fwd( geodetic_loc, dstdefn );
- if( pj_errno != 0 )
+ if( dstdefn->ctx->last_errno != 0 )
{
- if( (pj_errno != 33 /*EDOM*/ && pj_errno != 34 /*ERANGE*/ )
- && (pj_errno > 0 || pj_errno < -44 || point_count == 1
- || transient_error[-pj_errno] == 0 ) )
- return pj_errno;
+ if( (dstdefn->ctx->last_errno != 33 /*EDOM*/
+ && dstdefn->ctx->last_errno != 34 /*ERANGE*/ )
+ && (dstdefn->ctx->last_errno > 0
+ || dstdefn->ctx->last_errno < -44 || point_count == 1
+ || transient_error[-dstdefn->ctx->last_errno] == 0 ) )
+ return dstdefn->ctx->last_errno;
else
{
projected_loc.u = HUGE_VAL;
@@ -335,8 +342,8 @@ int pj_transform( PJ *srcdefn, PJ *dstdefn, long point_count, int point_offset,
{
int err;
- err = pj_adjust_axis( dstdefn->axis, 1, point_count, point_offset,
- x, y, z );
+ err = pj_adjust_axis( dstdefn->ctx, dstdefn->axis,
+ 1, point_count, point_offset, x, y, z );
if( err != 0 )
return err;
}
@@ -356,8 +363,7 @@ int pj_geodetic_to_geocentric( double a, double es,
double b;
int i;
GeocentricInfo gi;
-
- pj_errno = 0;
+ int ret_errno = 0;
if( es == 0.0 )
b = a;
@@ -366,8 +372,7 @@ int pj_geodetic_to_geocentric( double a, double es,
if( pj_Set_Geocentric_Parameters( &gi, a, b ) != 0 )
{
- pj_errno = PJD_ERR_GEOCENTRIC;
- return pj_errno;
+ return PJD_ERR_GEOCENTRIC;
}
for( i = 0; i < point_count; i++ )
@@ -380,13 +385,13 @@ int pj_geodetic_to_geocentric( double a, double es,
if( pj_Convert_Geodetic_To_Geocentric( &gi, y[io], x[io], z[io],
x+io, y+io, z+io ) != 0 )
{
- pj_errno = -14;
+ ret_errno = -14;
x[io] = y[io] = HUGE_VAL;
/* but keep processing points! */
}
}
- return pj_errno;
+ return ret_errno;
}
/************************************************************************/
@@ -409,8 +414,7 @@ int pj_geocentric_to_geodetic( double a, double es,
if( pj_Set_Geocentric_Parameters( &gi, a, b ) != 0 )
{
- pj_errno = PJD_ERR_GEOCENTRIC;
- return pj_errno;
+ return PJD_ERR_GEOCENTRIC;
}
for( i = 0; i < point_count; i++ )
@@ -484,8 +488,6 @@ int pj_geocentric_to_wgs84( PJ *defn,
{
int i;
- pj_errno = 0;
-
if( defn->datum_type == PJD_3PARAM )
{
for( i = 0; i < point_count; i++ )
@@ -534,8 +536,6 @@ int pj_geocentric_from_wgs84( PJ *defn,
{
int i;
- pj_errno = 0;
-
if( defn->datum_type == PJD_3PARAM )
{
for( i = 0; i < point_count; i++ )
@@ -589,8 +589,6 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn,
double src_a, src_es, dst_a, dst_es;
int z_is_temp = FALSE;
- pj_errno = 0;
-
/* -------------------------------------------------------------------- */
/* We cannot do any meaningful datum transformation if either */
/* the source or destination are of an unknown datum type */
@@ -624,7 +622,7 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn,
z_is_temp = TRUE;
}
-#define CHECK_RETURN {if( pj_errno != 0 && (pj_errno > 0 || transient_error[-pj_errno] == 0) ) { if( z_is_temp ) pj_dalloc(z); return pj_errno; }}
+#define CHECK_RETURN(defn) {if( defn->ctx->last_errno != 0 && (defn->ctx->last_errno > 0 || transient_error[-defn->ctx->last_errno] == 0) ) { if( z_is_temp ) pj_dalloc(z); return defn->ctx->last_errno; }}
/* -------------------------------------------------------------------- */
/* If this datum requires grid shifts, then apply it to geodetic */
@@ -633,7 +631,7 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn,
if( srcdefn->datum_type == PJD_GRIDSHIFT )
{
pj_apply_gridshift_2( srcdefn, 0, point_count, point_offset, x, y, z );
- CHECK_RETURN;
+ CHECK_RETURN(srcdefn);
src_a = SRS_WGS84_SEMIMAJOR;
src_es = SRS_WGS84_ESQUARED;
@@ -657,9 +655,10 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn,
/* -------------------------------------------------------------------- */
/* Convert to geocentric coordinates. */
/* -------------------------------------------------------------------- */
- pj_geodetic_to_geocentric( src_a, src_es,
- point_count, point_offset, x, y, z );
- CHECK_RETURN;
+ srcdefn->ctx->last_errno =
+ pj_geodetic_to_geocentric( src_a, src_es,
+ point_count, point_offset, x, y, z );
+ CHECK_RETURN(srcdefn);
/* -------------------------------------------------------------------- */
/* Convert between datums. */
@@ -668,22 +667,23 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn,
|| srcdefn->datum_type == PJD_7PARAM )
{
pj_geocentric_to_wgs84( srcdefn, point_count, point_offset,x,y,z);
- CHECK_RETURN;
+ CHECK_RETURN(srcdefn);
}
if( dstdefn->datum_type == PJD_3PARAM
|| dstdefn->datum_type == PJD_7PARAM )
{
pj_geocentric_from_wgs84( dstdefn, point_count,point_offset,x,y,z);
- CHECK_RETURN;
+ CHECK_RETURN(dstdefn);
}
/* -------------------------------------------------------------------- */
/* Convert back to geodetic coordinates. */
/* -------------------------------------------------------------------- */
- pj_geocentric_to_geodetic( dst_a, dst_es,
- point_count, point_offset, x, y, z );
- CHECK_RETURN;
+ dstdefn->ctx->last_errno =
+ pj_geocentric_to_geodetic( dst_a, dst_es,
+ point_count, point_offset, x, y, z );
+ CHECK_RETURN(dstdefn);
}
/* -------------------------------------------------------------------- */
@@ -692,7 +692,7 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn,
if( dstdefn->datum_type == PJD_GRIDSHIFT )
{
pj_apply_gridshift_2( dstdefn, 1, point_count, point_offset, x, y, z );
- CHECK_RETURN;
+ CHECK_RETURN(dstdefn);
}
if( z_is_temp )
@@ -707,7 +707,8 @@ int pj_datum_transform( PJ *srcdefn, PJ *dstdefn,
/* Normalize or de-normalized the x/y/z axes. The normal form */
/* is "enu" (easting, northing, up). */
/************************************************************************/
-static int pj_adjust_axis( const char *axis, int denormalize_flag,
+static int pj_adjust_axis( projCtx ctx,
+ const char *axis, int denormalize_flag,
long point_count, int point_offset,
double *x, double *y, double *z )
@@ -750,7 +751,7 @@ static int pj_adjust_axis( const char *axis, int denormalize_flag,
case 'd':
if( z ) z[point_offset*i] = -value; break;
default:
- pj_errno = PJD_ERR_AXIS;
+ pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
return PJD_ERR_AXIS;
}
} /* i_axis */
@@ -795,7 +796,7 @@ static int pj_adjust_axis( const char *axis, int denormalize_flag,
case 'd':
target[point_offset*i] = -z_in; break;
default:
- pj_errno = PJD_ERR_AXIS;
+ pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
return PJD_ERR_AXIS;
}
} /* i_axis */
diff --git a/src/pj_utils.c b/src/pj_utils.c
index d1193cd2..89f5bda2 100644
--- a/src/pj_utils.c
+++ b/src/pj_utils.c
@@ -108,7 +108,7 @@ PJ *pj_latlong_from_proj( PJ *pj_in )
}
else
{
- pj_errno = -13;
+ pj_ctx_set_errno( pj_in->ctx, -13 );
return NULL;
}
@@ -151,6 +151,6 @@ PJ *pj_latlong_from_proj( PJ *pj_in )
sprintf( defn+strlen(defn), " +pm=%s",
pj_param(pj_in->params,"spm").s );
- return pj_init_plus( defn );
+ return pj_init_plus_ctx( pj_in->ctx, defn );
}
diff --git a/src/proj_api.h b/src/proj_api.h
index d1f643b6..287d532f 100644
--- a/src/proj_api.h
+++ b/src/proj_api.h
@@ -55,8 +55,10 @@ extern int pj_errno; /* global error return code */
typedef void *projPJ;
#define projXY projUV
#define projLP projUV
+ typedef void *projCtx;
#else
typedef PJ *projPJ;
+ typedef projCtx_t *projCtx;
# define projXY XY
# define projLP LP
#endif
@@ -77,7 +79,7 @@ int pj_geodetic_to_geocentric( double a, double es,
long point_count, int point_offset,
double *x, double *y, double *z );
int pj_compare_datums( projPJ srcdefn, projPJ dstdefn );
-int pj_apply_gridshift( const char *, int,
+int pj_apply_gridshift( projCtx, const char *, int,
long point_count, int point_offset,
double *x, double *y, double *z );
void pj_deallocate_grids(void);
@@ -89,6 +91,8 @@ void pj_set_finder( const char *(*)(const char *) );
void pj_set_searchpath ( int count, const char **path );
projPJ pj_init(int, char **);
projPJ pj_init_plus(const char *);
+projPJ pj_init_ctx( projCtx, int, char ** );
+projPJ pj_init_plus_ctx( projCtx, const char * );
char *pj_get_def(projPJ, int);
projPJ pj_latlong_from_proj( projPJ );
void *pj_malloc(size_t);
@@ -100,6 +104,26 @@ void pj_acquire_lock(void);
void pj_release_lock(void);
void pj_cleanup_lock(void);
+projCtx pj_get_default_ctx(void);
+projCtx pj_get_ctx( projPJ );
+void pj_set_ctx( projPJ, projCtx );
+projCtx pj_ctx_alloc(void);
+void pj_ctx_free( projCtx );
+int pj_ctx_get_errno( projCtx );
+void pj_ctx_set_errno( projCtx, int );
+void pj_ctx_set_debug( projCtx, int );
+void pj_ctx_set_logger( projCtx, void (*)(void *, int, const char *) );
+void pj_ctx_set_app_data( projCtx, void * );
+void *pj_ctx_get_app_data( projCtx );
+
+void pj_log( projCtx ctx, int level, const char *fmt, ... );
+void pj_stderr_logger( void *, int, const char * );
+
+#define PJ_LOG_NONE 0
+#define PJ_LOG_ERROR 1
+#define PJ_LOG_DEBUG_MAJOR 2
+#define PJ_LOG_DEBUG_MINOR 3
+
#ifdef __cplusplus
}
#endif
diff --git a/src/projects.h b/src/projects.h
index 6a91ebda..b7d69bfb 100644
--- a/src/projects.h
+++ b/src/projects.h
@@ -124,6 +124,14 @@ extern double hypot(double, double);
#define DIR_CHAR '/'
#endif
+/* proj thread context */
+typedef struct {
+ int last_errno;
+ int debug_level;
+ void (*logger)(void *, int, const char *);
+ void *app_data;
+} projCtx_t;
+
/* datum_type values */
#define PJD_UNKNOWN 0
#define PJD_3PARAM 1
@@ -208,6 +216,7 @@ typedef struct ARG_list {
typedef struct PJconsts {
+ projCtx_t *ctx;
XY (*fwd)(LP, struct PJconsts *);
LP (*inv)(XY, struct PJconsts *);
void (*spc)(LP, struct PJconsts *, struct FACTORS *);
@@ -349,8 +358,8 @@ double adjlon(double);
double aacos(double), aasin(double), asqrt(double), aatan2(double, double);
PVALUE pj_param(paralist *, const char *);
paralist *pj_mkparam(char *);
-int pj_ell_set(paralist *, double *, double *);
-int pj_datum_set(paralist *, PJ *);
+int pj_ell_set(projCtx ctx, paralist *, double *, double *);
+int pj_datum_set(projCtx,paralist *, PJ *);
int pj_prime_meridian_set(paralist *, PJ *);
int pj_angular_units_set(paralist *, PJ *);
@@ -371,7 +380,7 @@ double *pj_authset(double);
double pj_authlat(double, double *);
COMPLEX pj_zpoly1(COMPLEX, COMPLEX *, int);
COMPLEX pj_zpolyd1(COMPLEX, COMPLEX *, int, COMPLEX *);
-FILE *pj_open_lib(char *, char *);
+FILE *pj_open_lib(projCtx, char *, char *);
int pj_deriv(LP, double, PJ *, struct DERIVS *);
int pj_factors(LP, PJ *, double, struct FACTORS *);
@@ -401,9 +410,9 @@ int bch2bps(projUV, projUV, projUV **, int, int);
/* nadcon related protos */
LP nad_intr(LP, struct CTABLE *);
LP nad_cvt(LP, int, struct CTABLE *);
-struct CTABLE *nad_init(char *);
-struct CTABLE *nad_ctable_init( FILE * fid );
-int nad_ctable_load( struct CTABLE *, FILE * fid );
+struct CTABLE *nad_init(projCtx ctx, char *);
+struct CTABLE *nad_ctable_init( projCtx ctx, FILE * fid );
+int nad_ctable_load( projCtx ctx, struct CTABLE *, FILE * fid );
void nad_free(struct CTABLE *);
/* higher level handling of datum grid shift files */
@@ -411,16 +420,17 @@ void nad_free(struct CTABLE *);
int pj_apply_gridshift_2( PJ *defn, int inverse,
long point_count, int point_offset,
double *x, double *y, double *z );
-int pj_apply_gridshift_3( PJ_GRIDINFO **gridlist, int gridlist_count,
+int pj_apply_gridshift_3( projCtx ctx,
+ PJ_GRIDINFO **gridlist, int gridlist_count,
int inverse, long point_count, int point_offset,
double *x, double *y, double *z );
-PJ_GRIDINFO **pj_gridlist_from_nadgrids( const char *, int * );
+PJ_GRIDINFO **pj_gridlist_from_nadgrids( projCtx, const char *, int * );
void pj_deallocate_grids();
-PJ_GRIDINFO *pj_gridinfo_init( const char * );
-int pj_gridinfo_load( PJ_GRIDINFO * );
-void pj_gridinfo_free( PJ_GRIDINFO * );
+PJ_GRIDINFO *pj_gridinfo_init( projCtx, const char * );
+int pj_gridinfo_load( projCtx, PJ_GRIDINFO * );
+void pj_gridinfo_free( projCtx, PJ_GRIDINFO * );
void *proj_mdist_ini(double);
double proj_mdist(double, double, double, const void *);