diff options
| author | Frank Warmerdam <warmerdam@pobox.com> | 2010-06-11 01:51:24 +0000 |
|---|---|---|
| committer | Frank Warmerdam <warmerdam@pobox.com> | 2010-06-11 01:51:24 +0000 |
| commit | ec678c07c2acb83da8a2187c541b8a2e452dec4b (patch) | |
| tree | a4c004a6e88d7330fe9d1c6ed793129831b5bdca /src | |
| parent | a7290836114dc82b35eceb1efcb5ecdf605d335f (diff) | |
| download | PROJ-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.am | 2 | ||||
| -rw-r--r-- | src/Makefile.in | 10 | ||||
| -rw-r--r-- | src/PJ_tmerc.c | 4 | ||||
| -rw-r--r-- | src/cs2cs.c | 4 | ||||
| -rw-r--r-- | src/geod_set.c | 2 | ||||
| -rw-r--r-- | src/multistresstest.c | 111 | ||||
| -rw-r--r-- | src/nad2nad.c | 4 | ||||
| -rw-r--r-- | src/nad_init.c | 21 | ||||
| -rw-r--r-- | src/pj_apply_gridshift.c | 55 | ||||
| -rw-r--r-- | src/pj_apply_vgridshift.c | 15 | ||||
| -rw-r--r-- | src/pj_ctx.c | 179 | ||||
| -rw-r--r-- | src/pj_datum_set.c | 4 | ||||
| -rw-r--r-- | src/pj_ell_set.c | 14 | ||||
| -rw-r--r-- | src/pj_factors.c | 4 | ||||
| -rw-r--r-- | src/pj_fwd.c | 9 | ||||
| -rw-r--r-- | src/pj_gridinfo.c | 93 | ||||
| -rw-r--r-- | src/pj_gridlist.c | 14 | ||||
| -rw-r--r-- | src/pj_init.c | 71 | ||||
| -rw-r--r-- | src/pj_inv.c | 8 | ||||
| -rw-r--r-- | src/pj_log.c | 73 | ||||
| -rw-r--r-- | src/pj_open_lib.c | 10 | ||||
| -rw-r--r-- | src/pj_transform.c | 111 | ||||
| -rw-r--r-- | src/pj_utils.c | 4 | ||||
| -rw-r--r-- | src/proj_api.h | 26 | ||||
| -rw-r--r-- | src/projects.h | 32 |
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 *); |
