diff options
Diffstat (limited to 'src/proj_4D_api.c')
| -rw-r--r-- | src/proj_4D_api.c | 238 |
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; |
