diff options
Diffstat (limited to 'src/pipeline.cpp')
| -rw-r--r-- | src/pipeline.cpp | 251 |
1 files changed, 119 insertions, 132 deletions
diff --git a/src/pipeline.cpp b/src/pipeline.cpp index 847f8194..bc6708b0 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -101,6 +101,7 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-20 #include <stddef.h> #include <string.h> #include <stack> +#include <vector> #include "geodesic.h" #include "proj.h" @@ -112,12 +113,25 @@ PROJ_HEAD(push, "Save coordinate value on pipeline stack"); /* Projection specific elements for the PJ object */ namespace { // anonymous namespace + +struct Step { + PJ* pj = nullptr; + + Step(PJ* pjIn): pj(pjIn) {} + Step(Step&& other): pj(std::move(other.pj)) { other.pj = nullptr; } + Step(const Step&) = delete; + Step& operator=(const Step&) = delete; + + ~Step() { + proj_destroy(pj); + } +}; + struct pj_opaque { - int steps; - char **argv; - char **current_argv; - PJ **pipeline; - std::stack<double> *stack[4]; + char **argv = nullptr; + char **current_argv = nullptr; + std::vector<Step> steps{}; + std::stack<double> stack[4]; }; struct pj_opaque_pushpop { @@ -138,32 +152,27 @@ static PJ_LP pipeline_reverse (PJ_XY xy, PJ *P); void pj_pipeline_assign_context_to_steps( PJ* P, PJ_CONTEXT* ctx ) { - for (int i = 1; i <= static_cast<struct pj_opaque*>(P->opaque)->steps; i++) - proj_assign_context(static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], ctx); + auto opaque = static_cast<struct pj_opaque*>(P->opaque); + for( auto& step: opaque->steps ) + proj_assign_context(step.pj, ctx); } static PJ_COORD pipeline_forward_4d (PJ_COORD point, PJ *P) { - int i, first_step, last_step; - - first_step = 1; - last_step = static_cast<struct pj_opaque*>(P->opaque)->steps + 1; - - for (i = first_step; i != last_step; i++) - point = proj_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_FWD, point); + auto opaque = static_cast<struct pj_opaque*>(P->opaque); + for( auto& step: opaque->steps ) + point = proj_trans (step.pj, PJ_FWD, point); return point; } static PJ_COORD pipeline_reverse_4d (PJ_COORD point, PJ *P) { - int i, first_step, last_step; - - first_step = static_cast<struct pj_opaque*>(P->opaque)->steps; - last_step = 0; - - for (i = first_step; i != last_step; i--) - point = proj_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_INV, point); + auto opaque = static_cast<struct pj_opaque*>(P->opaque); + for( auto it = opaque->steps.rbegin(); it != opaque->steps.rend(); ++it ) + { + point = proj_trans (it->pj, PJ_INV, point); + } return point; } @@ -173,11 +182,10 @@ static PJ_COORD pipeline_reverse_4d (PJ_COORD point, PJ *P) { static PJ_XYZ pipeline_forward_3d (PJ_LPZ lpz, PJ *P) { PJ_COORD point = {{0,0,0,0}}; - int i; point.lpz = lpz; - - for (i = 1; i <= static_cast<struct pj_opaque*>(P->opaque)->steps; i++) - point = pj_approx_3D_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_FWD, point); + auto opaque = static_cast<struct pj_opaque*>(P->opaque); + for( auto& step: opaque->steps ) + point = pj_approx_3D_trans (step.pj, PJ_FWD, point); return point.xyz; } @@ -185,11 +193,12 @@ static PJ_XYZ pipeline_forward_3d (PJ_LPZ lpz, PJ *P) { static PJ_LPZ pipeline_reverse_3d (PJ_XYZ xyz, PJ *P) { PJ_COORD point = {{0,0,0,0}}; - int i; point.xyz = xyz; - - for (i = static_cast<struct pj_opaque*>(P->opaque)->steps; i > 0 ; i--) - point = pj_approx_3D_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_INV, point); + auto opaque = static_cast<struct pj_opaque*>(P->opaque); + for( auto it = opaque->steps.rbegin(); it != opaque->steps.rend(); ++it ) + { + point = proj_trans (it->pj, PJ_INV, point); + } return point.lpz; } @@ -199,11 +208,10 @@ static PJ_LPZ pipeline_reverse_3d (PJ_XYZ xyz, PJ *P) { static PJ_XY pipeline_forward (PJ_LP lp, PJ *P) { PJ_COORD point = {{0,0,0,0}}; - int i; point.lp = lp; - - for (i = 1; i <= static_cast<struct pj_opaque*>(P->opaque)->steps; i++) - point = pj_approx_2D_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_FWD, point); + auto opaque = static_cast<struct pj_opaque*>(P->opaque); + for( auto& step: opaque->steps ) + point = pj_approx_2D_trans (step.pj, PJ_FWD, point); return point.xy; } @@ -211,10 +219,12 @@ static PJ_XY pipeline_forward (PJ_LP lp, PJ *P) { static PJ_LP pipeline_reverse (PJ_XY xy, PJ *P) { PJ_COORD point = {{0,0,0,0}}; - int i; point.xy = xy; - for (i = static_cast<struct pj_opaque*>(P->opaque)->steps; i > 0 ; i--) - point = pj_approx_2D_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_INV, point); + auto opaque = static_cast<struct pj_opaque*>(P->opaque); + for( auto it = opaque->steps.rbegin(); it != opaque->steps.rend(); ++it ) + { + point = pj_approx_2D_trans (it->pj, PJ_INV, point); + } return point.lp; } @@ -223,44 +233,24 @@ static PJ_LP pipeline_reverse (PJ_XY xy, PJ *P) { static PJ *destructor (PJ *P, int errlev) { - int i; if (nullptr==P) return nullptr; if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - /* Deallocate each pipeline step, then pipeline array */ - if (nullptr!=static_cast<struct pj_opaque*>(P->opaque)->pipeline) - for (i = 0; i < static_cast<struct pj_opaque*>(P->opaque)->steps; i++) - proj_destroy (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i+1]); - pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->pipeline); + auto opaque = static_cast<struct pj_opaque*>(P->opaque); - pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->argv); - pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->current_argv); + pj_dealloc (opaque->argv); + pj_dealloc (opaque->current_argv); - for (i=0; i<4; i++) - delete static_cast<struct pj_opaque*>(P->opaque)->stack[i]; + delete opaque; + P->opaque = nullptr; return pj_default_destructor(P, errlev); } -static PJ *pj_create_pipeline (PJ *P, size_t steps) { - - /* Room for the pipeline: An array of PJ * with room for sentinels at both ends */ - static_cast<struct pj_opaque*>(P->opaque)->pipeline = static_cast<PJ**>(pj_calloc (steps + 2, sizeof(PJ *))); - if (nullptr==static_cast<struct pj_opaque*>(P->opaque)->pipeline) - return nullptr; - - static_cast<struct pj_opaque*>(P->opaque)->steps = (int)steps; - - return P; -} - - - - /* count the number of args in pipeline definition, and mark all args as used */ static size_t argc_params (paralist *params) { size_t argc = 0; @@ -345,28 +335,30 @@ static void set_ellipsoid(PJ *P) { } -static enum pj_io_units get_next_non_whatever_unit(void *pipeline_data, int step, PJ_DIRECTION dir) { - PJ **pipeline = static_cast<struct pj_opaque*>(pipeline_data)->pipeline; - int nsteps = static_cast<struct pj_opaque*>(pipeline_data)->steps; - int i; +static enum pj_io_units get_next_non_whatever_unit(struct pj_opaque* opaque, size_t step, PJ_DIRECTION dir) { + const auto& steps = opaque->steps; + const auto nsteps = steps.size(); if (dir == PJ_FWD) { - for (i = step+1; i<=nsteps; i++) { - if (pj_left(pipeline[i]) != pj_right(pipeline[i])) - return pj_left(pipeline[i]); - if (pj_left(pipeline[i]) != PJ_IO_UNITS_WHATEVER) - return pj_left(pipeline[i]); - if (pj_right(pipeline[i]) != PJ_IO_UNITS_WHATEVER) - return pj_right(pipeline[i]); + for (size_t i = step+1; i<nsteps; i++) { + auto pj = steps[i].pj; + if (pj_left(pj) != pj_right(pj)) + return pj_left(pj); + if (pj_left(pj) != PJ_IO_UNITS_WHATEVER) + return pj_left(pj); + if (pj_right(pj) != PJ_IO_UNITS_WHATEVER) + return pj_right(pj); } } else { - for (i=step; i>1; i--) { - if (pj_right(pipeline[i]) != pj_left(pipeline[i])) - return pj_right(pipeline[i]); - if (pj_right(pipeline[i]) != PJ_IO_UNITS_WHATEVER) - return pj_right(pipeline[i]); - if (pj_left(pipeline[i]) != PJ_IO_UNITS_WHATEVER) - return pj_left(pipeline[i]); + for (size_t i=step; i>0;) { + i--; + auto pj = steps[i].pj; + if (pj_right(pj) != pj_left(pj)) + return pj_right(pj); + if (pj_right(pj) != PJ_IO_UNITS_WHATEVER) + return pj_right(pj); + if (pj_left(pj) != PJ_IO_UNITS_WHATEVER) + return pj_left(pj); } } return PJ_IO_UNITS_WHATEVER; @@ -396,20 +388,17 @@ PJ *OPERATION(pipeline,0) { P->skip_inv_finalize = 1; - P->opaque = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof(struct pj_opaque))); + P->opaque = new (std::nothrow) pj_opaque(); if (nullptr==P->opaque) return destructor(P, ENOMEM); - /* initialize stack */ - for (i=0; i<4; i++) - static_cast<struct pj_opaque*>(P->opaque)->stack[i] = new std::stack<double>; - argc = (int)argc_params (P->params); - static_cast<struct pj_opaque*>(P->opaque)->argv = argv = argv_params (P->params, argc); + auto opaque = static_cast<struct pj_opaque*>(P->opaque); + opaque->argv = argv = argv_params (P->params, argc); if (nullptr==argv) return destructor (P, ENOMEM); - static_cast<struct pj_opaque*>(P->opaque)->current_argv = current_argv = static_cast<char**>(pj_calloc (argc, sizeof (char *))); + opaque->current_argv = current_argv = static_cast<char**>(pj_calloc (argc, sizeof (char *))); if (nullptr==current_argv) return destructor (P, ENOMEM); @@ -435,7 +424,6 @@ PJ *OPERATION(pipeline,0) { } } nsteps--; /* Last instance of +step is just a sentinel */ - static_cast<struct pj_opaque*>(P->opaque)->steps = nsteps; if (-1==i_pipeline) return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: no pipeline def */ @@ -443,10 +431,6 @@ PJ *OPERATION(pipeline,0) { if (0==nsteps) return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: no pipeline def */ - /* Make room for the pipeline and execution indicators */ - if (nullptr==pj_create_pipeline (P, nsteps)) - return destructor (P, ENOMEM); - set_ellipsoid(P); /* Now loop over all steps, building a new set of arguments for each init */ @@ -498,14 +482,14 @@ PJ *OPERATION(pipeline,0) { next_step->inverted = next_step->inverted == 0 ? 1 : 0; } - static_cast<struct pj_opaque*>(P->opaque)->pipeline[i+1] = next_step; + opaque->steps.emplace_back(next_step); proj_log_trace (P, "Pipeline at [%p]: step at [%p] (%s) done", P, next_step, current_argv[0]); } /* Require a forward path through the pipeline */ - for (i = 1; i <= nsteps; i++) { - PJ *Q = static_cast<struct pj_opaque*>(P->opaque)->pipeline[i]; + for( auto& step: opaque->steps) { + PJ *Q = step.pj; if ( ( Q->inverted && (Q->inv || Q->inv3d || Q->fwd4d) ) || (!Q->inverted && (Q->fwd || Q->fwd3d || Q->fwd4d) ) ) { continue; @@ -516,8 +500,8 @@ PJ *OPERATION(pipeline,0) { } /* determine if an inverse operation is possible */ - for (i = 1; i <= nsteps; i++) { - PJ *Q = static_cast<struct pj_opaque*>(P->opaque)->pipeline[i]; + for( auto& step: opaque->steps) { + PJ *Q = step.pj; if ( pj_has_inverse(Q) ) { continue; } else { @@ -534,31 +518,33 @@ PJ *OPERATION(pipeline,0) { /* proj=pipeline step proj=unitconvert xy_in=deg xy_out=rad step ... */ /* where the left-hand side units of the first step shouldn't be changed to RADIANS */ /* as it will result in deg->rad conversions in cs2cs and other applications. */ - PJ **pipeline = static_cast<struct pj_opaque*>(P->opaque)->pipeline; - for (i=1; i<=nsteps; i++) { - if (pj_left(pipeline[i]) == PJ_IO_UNITS_WHATEVER && pj_right(pipeline[i]) == PJ_IO_UNITS_WHATEVER) { - pipeline[i]->left = get_next_non_whatever_unit(P->opaque, i, PJ_FWD); - pipeline[i]->right = get_next_non_whatever_unit(P->opaque, i, PJ_FWD); + for (i=0; i<nsteps; i++) { + auto pj = opaque->steps[i].pj; + if (pj_left(pj) == PJ_IO_UNITS_WHATEVER && pj_right(pj) == PJ_IO_UNITS_WHATEVER) { + pj->left = get_next_non_whatever_unit(opaque, i, PJ_FWD); + pj->right = get_next_non_whatever_unit(opaque, i, PJ_FWD); } } - for (i=nsteps; i>0; i--) { - if (pj_left(pipeline[i]) == PJ_IO_UNITS_WHATEVER && pj_right(pipeline[i]) == PJ_IO_UNITS_WHATEVER) { - pipeline[i]->right = get_next_non_whatever_unit(P->opaque, i, PJ_INV); - pipeline[i]->left = get_next_non_whatever_unit(P->opaque, i, PJ_INV); + for (i=nsteps; i>0;) { + --i; + auto pj = opaque->steps[i].pj; + if (pj_left(pj) == PJ_IO_UNITS_WHATEVER && pj_right(pj) == PJ_IO_UNITS_WHATEVER) { + pj->right = get_next_non_whatever_unit(opaque, i, PJ_INV); + pj->left = get_next_non_whatever_unit(opaque, i, PJ_INV); } } /* Check that units between each steps match each other, fail if they don't */ - for (i = 1; i < nsteps; i++) { - enum pj_io_units curr_step_output = pj_right (pipeline[i]); - enum pj_io_units next_step_input = pj_left (pipeline[i+1]); + for (i = 0; i + 1 < nsteps; i++) { + enum pj_io_units curr_step_output = pj_right (opaque->steps[i].pj); + enum pj_io_units next_step_input = pj_left (opaque->steps[i+1].pj); if ( curr_step_output == PJ_IO_UNITS_WHATEVER || next_step_input == PJ_IO_UNITS_WHATEVER ) continue; if ( curr_step_output != next_step_input ) { - proj_log_error (P, "Pipeline: Mismatched units between step %d and %d", i, i+1); + proj_log_error (P, "Pipeline: Mismatched units between step %d and %d", i+1, i+2); return destructor (P, PJD_ERR_MALFORMED_PIPELINE); } } @@ -566,10 +552,10 @@ PJ *OPERATION(pipeline,0) { proj_log_trace (P, "Pipeline: %d steps built. Determining i/o characteristics", nsteps); /* Determine forward input (= reverse output) data type */ - P->left = pj_left (static_cast<struct pj_opaque*>(P->opaque)->pipeline[1]); + P->left = pj_left (opaque->steps.front().pj); /* Now, correspondingly determine forward output (= reverse input) data type */ - P->right = pj_right (static_cast<struct pj_opaque*>(P->opaque)->pipeline[nsteps]); + P->right = pj_right (opaque->steps.back().pj); return P; } @@ -581,13 +567,13 @@ static PJ_COORD push(PJ_COORD point, PJ *P) { struct pj_opaque_pushpop *opaque = static_cast<struct pj_opaque_pushpop*>(P->opaque); if (opaque->v1) - pipeline->stack[0]->push(point.v[0]); + pipeline->stack[0].push(point.v[0]); if (opaque->v2) - pipeline->stack[1]->push(point.v[1]); + pipeline->stack[1].push(point.v[1]); if (opaque->v3) - pipeline->stack[2]->push(point.v[2]); + pipeline->stack[2].push(point.v[2]); if (opaque->v4) - pipeline->stack[3]->push(point.v[3]); + pipeline->stack[3].push(point.v[3]); return point; } @@ -599,24 +585,24 @@ static PJ_COORD pop(PJ_COORD point, PJ *P) { struct pj_opaque *pipeline = static_cast<struct pj_opaque*>(P->parent->opaque); struct pj_opaque_pushpop *opaque = static_cast<struct pj_opaque_pushpop*>(P->opaque); - if (opaque->v1 && !pipeline->stack[0]->empty()) { - point.v[0] = pipeline->stack[0]->top(); - pipeline->stack[0]->pop(); + if (opaque->v1 && !pipeline->stack[0].empty()) { + point.v[0] = pipeline->stack[0].top(); + pipeline->stack[0].pop(); } - if (opaque->v2 && !pipeline->stack[1]->empty()) { - point.v[1] = pipeline->stack[1]->top(); - pipeline->stack[1]->pop(); + if (opaque->v2 && !pipeline->stack[1].empty()) { + point.v[1] = pipeline->stack[1].top(); + pipeline->stack[1].pop(); } - if (opaque->v3 && !pipeline->stack[2]->empty()) { - point.v[2] = pipeline->stack[2]->top(); - pipeline->stack[2]->pop(); + if (opaque->v3 && !pipeline->stack[2].empty()) { + point.v[2] = pipeline->stack[2].top(); + pipeline->stack[2].pop(); } - if (opaque->v4 && !pipeline->stack[3]->empty()) { - point.v[3] = pipeline->stack[3]->top(); - pipeline->stack[3]->pop(); + if (opaque->v4 && !pipeline->stack[3].empty()) { + point.v[3] = pipeline->stack[3].top(); + pipeline->stack[3].pop(); } return point; @@ -625,21 +611,22 @@ static PJ_COORD pop(PJ_COORD point, PJ *P) { static PJ *setup_pushpop(PJ *P) { - P->opaque = static_cast<struct pj_opaque_pushpop*>(pj_calloc (1, sizeof(struct pj_opaque_pushpop))); + auto opaque = static_cast<struct pj_opaque_pushpop*>(pj_calloc (1, sizeof(struct pj_opaque_pushpop))); + P->opaque = opaque; if (nullptr==P->opaque) return destructor(P, ENOMEM); if (pj_param_exists(P->params, "v_1")) - static_cast<struct pj_opaque_pushpop*>(P->opaque)->v1 = true; + opaque->v1 = true; if (pj_param_exists(P->params, "v_2")) - static_cast<struct pj_opaque_pushpop*>(P->opaque)->v2 = true; + opaque->v2 = true; if (pj_param_exists(P->params, "v_3")) - static_cast<struct pj_opaque_pushpop*>(P->opaque)->v3 = true; + opaque->v3 = true; if (pj_param_exists(P->params, "v_4")) - static_cast<struct pj_opaque_pushpop*>(P->opaque)->v4 = true; + opaque->v4 = true; P->left = PJ_IO_UNITS_WHATEVER; P->right = PJ_IO_UNITS_WHATEVER; |
