aboutsummaryrefslogtreecommitdiff
path: root/src/proj_4D_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/proj_4D_api.c')
-rw-r--r--src/proj_4D_api.c238
1 files changed, 142 insertions, 96 deletions
diff --git a/src/proj_4D_api.c b/src/proj_4D_api.c
index 0d50407f..42e3cbf9 100644
--- a/src/proj_4D_api.c
+++ b/src/proj_4D_api.c
@@ -724,70 +724,113 @@ PJ_CONTEXT *proj_context_destroy (PJ_CONTEXT *ctx) {
}
+
+
+
+
/*****************************************************************************/
-PJ_INFO proj_info(void) {
+static char *path_append (char *buf, const char *app, size_t *buf_size) {
/******************************************************************************
- Basic info about the current instance of the PROJ.4 library.
+ Helper for proj_info() below. Append app to buf, separated by a
+ semicolon. Also handle allocation of longer buffer if needed.
+
+ Returns buffer and adjusts *buf_size through provided pointer arg.
+******************************************************************************/
+ char *p;
+ size_t len, applen = 0, buflen = 0;
+#ifdef _WIN32
+ char *delim = ";";
+#else
+ char *delim = ":";
+#endif
+
+ /* Nothing to do? */
+ if (0 == app)
+ return buf;
+ applen = strlen (app);
+ if (0 == applen)
+ return buf;
+
+ /* Start checking whether buf is long enough */
+ if (0 != buf)
+ buflen = strlen (buf);
+ len = buflen+applen+strlen (delim) + 1;
+
+ /* "pj_realloc", so to speak */
+ if (*buf_size < len) {
+ p = pj_calloc (2 * len, sizeof (char));
+ if (0==p) {
+ pj_dealloc (buf);
+ return 0;
+ }
+ *buf_size = 2 * len;
+ if (buf != 0)
+ strcpy (p, buf);
+ pj_dealloc (buf);
+ buf = p;
+ }
+
+ /* Only append a semicolon if something's already there */
+ if (0 != buflen)
+ strcat (buf, ";");
+ strcat (buf, app);
+ return buf;
+}
- Returns PJ_INFO struct. Searchpath member of the struct is truncated to 512
- characters.
+static const char *empty = {""};
+static char version[64] = {""};
+static PJ_INFO info = {0, 0, 0, 0, 0, 0, 0, 0};
+static volatile int info_initialized = 0;
+/*****************************************************************************/
+PJ_INFO proj_info (void) {
+/******************************************************************************
+ Basic info about the current instance of the PROJ.4 library.
+
+ Returns PJ_INFO struct.
******************************************************************************/
- PJ_INFO info;
const char * const *paths;
- char *tmpstr;
- int i, n;
- size_t len = 0;
+ size_t i, n;
+
+ size_t buf_size = 0;
+ char *buf = 0;
- memset(&info, 0, sizeof(PJ_INFO));
+ pj_acquire_lock ();
+
+ if (0!=info_initialized) {
+ pj_release_lock ();
+ return info;
+ }
info.major = PROJ_VERSION_MAJOR;
info.minor = PROJ_VERSION_MINOR;
info.patch = PROJ_VERSION_PATCH;
/* This is a controlled environment, so no risk of sprintf buffer
- overflow. A normal version string is xx.yy.zz which is 8 characters
- long and there is room for 64 bytes in the version string. */
- sprintf(info.version, "%d.%d.%d", info.major, info.minor, info.patch);
-
- pj_strlcpy(info.release, pj_get_release(), sizeof(info.release));
+ overflow. A normal version string is xx.yy.zz which is 8 characters
+ long and there is room for 64 bytes in the version string. */
+ sprintf (version, "%d.%d.%d", info.major, info.minor, info.patch);
+ info.searchpath = empty;
+ info.version = version;
+ info.release = pj_get_release ();
/* build search path string */
- tmpstr = getenv("HOME");
- if (tmpstr != NULL) {
- pj_strlcpy(info.searchpath, tmpstr, sizeof(info.searchpath));
- }
+ buf = path_append (buf, getenv ("HOME"), &buf_size);
+ buf = path_append (buf, getenv ("PROJ_LIB"), &buf_size);
- tmpstr = getenv("PROJ_LIB");
- if (tmpstr != NULL) {
- if (strlen(info.searchpath) != 0) {
- /* $HOME already in path */
- strcat(info.searchpath, ";");
- len = strlen(tmpstr);
- strncat(info.searchpath, tmpstr, sizeof(info.searchpath)-len-1);
- } else {
- /* path is empty */
- pj_strlcpy(info.searchpath, tmpstr, sizeof(info.searchpath));
- }
- }
-
- paths = proj_get_searchpath();
- n = proj_get_path_count();
+ paths = proj_get_searchpath ();
+ n = (size_t) proj_get_path_count ();
- for (i=0; i<n; i++) {
- if (strlen(info.searchpath)+strlen(paths[i]) >= 511)
- continue;
+ for (i = 0; i < n; i++)
+ buf = path_append (buf, paths[i], &buf_size);
+ info.searchpath = buf ? buf : empty;
- if (strlen(info.searchpath) != 0) {
- strcat(info.searchpath, ";");
- len = strlen(paths[i]);
- strncat(info.searchpath, paths[i], sizeof(info.searchpath)-len-1);
- } else {
- pj_strlcpy(info.searchpath, paths[i], sizeof(info.searchpath));
- }
- }
+ info.paths = paths;
+ info.path_count = n;
+ info_initialized = 1;
+ pj_release_lock ();
return info;
}
@@ -798,37 +841,41 @@ PJ_PROJ_INFO proj_pj_info(PJ *P) {
Basic info about a particular instance of a projection object.
Returns PJ_PROJ_INFO struct.
-
******************************************************************************/
- PJ_PROJ_INFO info;
+ PJ_PROJ_INFO pjinfo;
char *def;
- memset(&info, 0, sizeof(PJ_PROJ_INFO));
+ memset(&pjinfo, 0, sizeof(PJ_PROJ_INFO));
/* Expected accuracy of the transformation. Hardcoded for now, will be improved */
/* later. Most likely to be used when a transformation is set up with */
/* proj_create_crs_to_crs in a future version that leverages the EPSG database. */
- info.accuracy = -1.0;
+ pjinfo.accuracy = -1.0;
- if (!P) {
- return info;
- }
+ if (0==P)
+ return pjinfo;
/* projection id */
if (pj_param(P->ctx, P->params, "tproj").i)
- pj_strlcpy(info.id, pj_param(P->ctx, P->params, "sproj").s, sizeof(info.id));
+ pjinfo.id = pj_param(P->ctx, P->params, "sproj").s;
/* projection description */
- pj_strlcpy(info.description, P->descr, sizeof(info.description));
+ pjinfo.description = P->descr;
/* projection definition */
- def = pj_get_def(P, 0); /* pj_get_def takes a non-const PJ pointer */
- pj_strlcpy(info.definition, &def[1], sizeof(info.definition)); /* def includes a leading space */
- pj_dealloc(def);
-
- info.has_inverse = pj_has_inverse(P);
+ if (P->def_full)
+ def = P->def_full;
+ else
+ def = pj_get_def(P, 0); /* pj_get_def takes a non-const PJ pointer */
+ if (0==def)
+ pjinfo.definition = empty;
+ else
+ pjinfo.definition = pj_shrink (def);
+ /* Make pj_free clean this up eventually */
+ P->def_full = def;
- return info;
+ pjinfo.has_inverse = pj_has_inverse(P);
+ return pjinfo;
}
@@ -838,47 +885,49 @@ PJ_GRID_INFO proj_grid_info(const char *gridname) {
Information about a named datum grid.
Returns PJ_GRID_INFO struct.
-
******************************************************************************/
- PJ_GRID_INFO info;
+ PJ_GRID_INFO grinfo;
/*PJ_CONTEXT *ctx = proj_context_create(); */
PJ_CONTEXT *ctx = pj_get_default_ctx();
PJ_GRIDINFO *gridinfo = pj_gridinfo_init(ctx, gridname);
- memset(&info, 0, sizeof(PJ_GRID_INFO));
+ memset(&grinfo, 0, sizeof(PJ_GRID_INFO));
/* in case the grid wasn't found */
if (gridinfo->filename == NULL) {
pj_gridinfo_free(ctx, gridinfo);
- strcpy(info.format, "missing");
- return info;
+ strcpy(grinfo.format, "missing");
+ return grinfo;
}
+ /* The string copies below are automatically null-terminated due to */
+ /* the memset above, so strncpy is safe */
+
/* name of grid */
- pj_strlcpy(info.gridname, gridname, sizeof(info.gridname));
+ strncpy (grinfo.gridname, gridname, sizeof(grinfo.gridname) - 1);
/* full path of grid */
- pj_find_file(ctx, gridname, info.filename, sizeof(info.filename));
+ pj_find_file(ctx, gridname, grinfo.filename, sizeof(grinfo.filename) - 1);
/* grid format */
- pj_strlcpy(info.format, gridinfo->format, sizeof(info.format));
+ strncpy (grinfo.format, gridinfo->format, sizeof(grinfo.format) - 1);
/* grid size */
- info.n_lon = gridinfo->ct->lim.lam;
- info.n_lat = gridinfo->ct->lim.phi;
+ grinfo.n_lon = gridinfo->ct->lim.lam;
+ grinfo.n_lat = gridinfo->ct->lim.phi;
/* cell size */
- info.cs_lon = gridinfo->ct->del.lam;
- info.cs_lat = gridinfo->ct->del.phi;
+ grinfo.cs_lon = gridinfo->ct->del.lam;
+ grinfo.cs_lat = gridinfo->ct->del.phi;
/* bounds of grid */
- info.lowerleft = gridinfo->ct->ll;
- info.upperright.lam = info.lowerleft.lam + info.n_lon*info.cs_lon;
- info.upperright.phi = info.lowerleft.phi + info.n_lat*info.cs_lat;
+ grinfo.lowerleft = gridinfo->ct->ll;
+ grinfo.upperright.lam = grinfo.lowerleft.lam + grinfo.n_lon*grinfo.cs_lon;
+ grinfo.upperright.phi = grinfo.lowerleft.phi + grinfo.n_lat*grinfo.cs_lat;
pj_gridinfo_free(ctx, gridinfo);
- return info;
+ return grinfo;
}
@@ -897,27 +946,28 @@ PJ_INIT_INFO proj_init_info(const char *initname){
If the init file is found, but the metadata is missing, the value is
set to "Unknown".
-
******************************************************************************/
int file_found;
char param[80], key[74];
paralist *start, *next;
- PJ_INIT_INFO info;
+ PJ_INIT_INFO ininfo;
PJ_CONTEXT *ctx = pj_get_default_ctx();
- memset(&info, 0, sizeof(PJ_INIT_INFO));
+ memset(&ininfo, 0, sizeof(PJ_INIT_INFO));
- file_found = pj_find_file(ctx, initname, info.filename, sizeof(info.filename));
+ file_found = pj_find_file(ctx, initname, ininfo.filename, sizeof(ininfo.filename));
if (!file_found || strlen(initname) > 64) {
- return info;
+ return ininfo;
}
- pj_strlcpy(info.name, initname, sizeof(info.name));
- strcpy(info.origin, "Unknown");
- strcpy(info.version, "Unknown");
- strcpy(info.lastupdate, "Unknown");
+ /* The initial memset (0) makes strncpy safe here */
+ strncpy (ininfo.name, initname, sizeof(ininfo.name) - 1);
+ strcpy(ininfo.origin, "Unknown");
+ strcpy(ininfo.version, "Unknown");
+ strcpy(ininfo.lastupdate, "Unknown");
- pj_strlcpy(key, initname, 64); /* make room for ":metadata\0" at the end */
+ strncpy (key, initname, 64); /* make room for ":metadata\0" at the end */
+ key[64] = 0;
strncat(key, ":metadata", 9);
strcpy(param, "+init=");
strncat(param, key, 73);
@@ -925,24 +975,21 @@ PJ_INIT_INFO proj_init_info(const char *initname){
start = pj_mkparam(param);
pj_expand_init(ctx, start);
- if (pj_param(ctx, start, "tversion").i) {
- pj_strlcpy(info.version, pj_param(ctx, start, "sversion").s, sizeof(info.version));
- }
+ if (pj_param(ctx, start, "tversion").i)
+ strncpy(ininfo.version, pj_param(ctx, start, "sversion").s, sizeof(ininfo.version) - 1);
- if (pj_param(ctx, start, "torigin").i) {
- pj_strlcpy(info.origin, pj_param(ctx, start, "sorigin").s, sizeof(info.origin));
- }
+ if (pj_param(ctx, start, "torigin").i)
+ strncpy(ininfo.origin, pj_param(ctx, start, "sorigin").s, sizeof(ininfo.origin) - 1);
- if (pj_param(ctx, start, "tlastupdate").i) {
- pj_strlcpy(info.lastupdate, pj_param(ctx, start, "slastupdate").s, sizeof(info.lastupdate));
- }
+ if (pj_param(ctx, start, "tlastupdate").i)
+ strncpy(ininfo.lastupdate, pj_param(ctx, start, "slastupdate").s, sizeof(ininfo.lastupdate) - 1);
for ( ; start; start = next) {
next = start->next;
pj_dalloc(start);
}
- return info;
+ return ininfo;
}
@@ -957,7 +1004,6 @@ PJ_FACTORS proj_factors(PJ *P, LP lp) {
returns PJ_FACTORS. If unsuccessfull, error number is set and the
struct returned contains NULL data.
-
******************************************************************************/
PJ_FACTORS factors = {0,0,0, 0,0,0, 0,0, 0,0,0,0};
struct FACTORS f;