aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/4D_api.cpp26
-rw-r--r--src/ctx.cpp23
-rw-r--r--src/open_lib.cpp145
-rw-r--r--src/proj.h6
-rw-r--r--src/proj_internal.h12
5 files changed, 144 insertions, 68 deletions
diff --git a/src/4D_api.cpp b/src/4D_api.cpp
index e0d15773..cdfaa8b2 100644
--- a/src/4D_api.cpp
+++ b/src/4D_api.cpp
@@ -1006,7 +1006,6 @@ static char *path_append (char *buf, const char *app, size_t *buf_size) {
static const char *empty = {""};
static char version[64] = {""};
static PJ_INFO info = {0, 0, 0, nullptr, nullptr, nullptr, nullptr, 0};
-static volatile int info_initialized = 0;
/*****************************************************************************/
PJ_INFO proj_info (void) {
@@ -1015,19 +1014,11 @@ PJ_INFO proj_info (void) {
Returns PJ_INFO struct.
******************************************************************************/
- const char * const *paths;
- size_t i, n;
-
size_t buf_size = 0;
char *buf = nullptr;
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;
@@ -1037,7 +1028,6 @@ PJ_INFO proj_info (void) {
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 ();
@@ -1045,17 +1035,19 @@ PJ_INFO proj_info (void) {
buf = path_append (buf, getenv ("HOME"), &buf_size);
buf = path_append (buf, getenv ("PROJ_LIB"), &buf_size);
- paths = proj_get_searchpath ();
- n = (size_t) proj_get_path_count ();
+ auto ctx = pj_get_default_ctx();
+ if( ctx ) {
+ for( const auto& path: ctx->search_paths ) {
+ buf = path_append(buf, path.c_str(), &buf_size);
+ }
+ }
- for (i = 0; i < n; i++)
- buf = path_append (buf, paths[i], &buf_size);
+ pj_dalloc(const_cast<char*>(info.searchpath));
info.searchpath = buf ? buf : empty;
- info.paths = paths;
- info.path_count = n;
+ info.paths = ctx ? ctx->c_compat_paths : nullptr;
+ info.path_count = ctx ? static_cast<int>(ctx->search_paths.size()) : 0;
- info_initialized = 1;
pj_release_lock ();
return info;
}
diff --git a/src/ctx.cpp b/src/ctx.cpp
index a94eaf54..005070b0 100644
--- a/src/ctx.cpp
+++ b/src/ctx.cpp
@@ -100,6 +100,23 @@ projCtx_t projCtx_t::createDefault()
}
/************************************************************************/
+/* set_search_paths() */
+/************************************************************************/
+
+void projCtx_t::set_search_paths(const std::vector<std::string>& search_paths_in )
+{
+ search_paths = search_paths_in;
+ delete[] c_compat_paths;
+ c_compat_paths = nullptr;
+ if( !search_paths.empty() ) {
+ c_compat_paths = new const char*[search_paths.size()];
+ for( size_t i = 0; i < search_paths.size(); ++i ) {
+ c_compat_paths[i] = search_paths[i].c_str();
+ }
+ }
+}
+
+/************************************************************************/
/* projCtx_t(const projCtx_t& other) */
/************************************************************************/
@@ -110,6 +127,10 @@ projCtx_t::projCtx_t(const projCtx_t& other)
logger_app_data = other.logger_app_data;
fileapi = other.fileapi;
epsg_file_exists = other.epsg_file_exists;
+ set_search_paths(other.search_paths);
+ file_finder = other.file_finder;
+ file_finder_legacy = other.file_finder_legacy;
+ file_finder_user_data = other.file_finder_user_data;
}
/************************************************************************/
@@ -130,6 +151,7 @@ projCtx pj_get_default_ctx()
projCtx_t::~projCtx_t()
{
+ delete[] c_compat_paths;
proj_context_delete_cpp_context(cpp_context);
}
@@ -252,3 +274,4 @@ projFileAPI *pj_ctx_get_fileapi( projCtx ctx )
return nullptr;
return ctx->fileapi;
}
+
diff --git a/src/open_lib.cpp b/src/open_lib.cpp
index f4fa313f..b022b263 100644
--- a/src/open_lib.cpp
+++ b/src/open_lib.cpp
@@ -37,11 +37,7 @@
#include <string.h>
#include "proj_internal.h"
-#include "proj_internal.h"
-static const char *(*pj_finder)(const char *) = nullptr;
-static int path_count = 0;
-static char **search_path = nullptr;
static const char * proj_lib_name =
#ifdef PROJ_LIB
PROJ_LIB;
@@ -56,54 +52,98 @@ nullptr;
void pj_set_finder( const char *(*new_finder)(const char *) )
{
- pj_finder = new_finder;
+ auto ctx = pj_get_default_ctx();
+ if( ctx ) {
+ ctx->file_finder_legacy = new_finder;
+ }
}
/************************************************************************/
-/* pj_set_searchpath() */
-/* */
-/* Path control for callers that can't practically provide */
-/* pj_set_finder() style callbacks. Call with (0,NULL) as args */
-/* to clear the searchpath set. */
+/* proj_context_set_file_finder() */
/************************************************************************/
-void pj_set_searchpath ( int count, const char **path )
+/** \brief Assign a file finder callback to a context.
+ *
+ * This callback will be used whenever PROJ must open one of its resource files
+ * (proj.db database, grids, etc...)
+ *
+ * The callback will be called with the context currently in use at the moment
+ * where it is used (not necessarily the one provided during this call), and
+ * with the provided user_data (which may be NULL).
+ * The user_data must remain valid during the whole lifetime of the context.
+ *
+ * A finder set on the default context will be inherited by contexts created
+ * later.
+ *
+ * @param ctx PROJ context, or NULL for the default context.
+ * @param finder Finder callback. May be NULL
+ * @param user_data User data provided to the finder callback. May be NULL.
+ *
+ * @since PROJ 6.0
+ */
+void proj_context_set_file_finder(PJ_CONTEXT *ctx, proj_file_finder finder,
+ void* user_data)
{
- int i;
+ if( !ctx )
+ ctx = pj_get_default_ctx();
+ if( !ctx )
+ return;
+ ctx->file_finder = finder;
+ ctx->file_finder_user_data = user_data;
+}
- if (path_count > 0 && search_path != nullptr)
- {
- for (i = 0; i < path_count; i++)
- {
- pj_dalloc(search_path[i]);
- }
- pj_dalloc(search_path);
- path_count = 0;
- search_path = nullptr;
- }
+/************************************************************************/
+/* proj_context_set_search_paths() */
+/************************************************************************/
- if( count > 0 )
- {
- search_path = static_cast<char**>(pj_malloc(sizeof *search_path * count));
- for (i = 0; i < count; i++)
+
+/** \brief Sets search paths.
+ *
+ * Those search paths will be used whenever PROJ must open one of its resource files
+ * (proj.db database, grids, etc...)
+ *
+ * If set on the default context, they will be inherited by contexts created
+ * later.
+ *
+ * @param ctx PROJ context, or NULL for the default context.
+ * @param count_paths Number of paths. 0 if paths == NULL.
+ * @param paths Paths. May be NULL.
+ *
+ * @since PROJ 6.0
+ */
+void proj_context_set_search_paths(PJ_CONTEXT *ctx,
+ int count_paths,
+ const char* const* paths)
+{
+ if( !ctx )
+ ctx = pj_get_default_ctx();
+ if( !ctx )
+ return;
+ try {
+ std::vector<std::string> vector_of_paths;
+ for (int i = 0; i < count_paths; i++)
{
- search_path[i] = static_cast<char*>(pj_malloc(strlen(path[i]) + 1));
- strcpy(search_path[i], path[i]);
+ vector_of_paths.emplace_back(paths[i]);
}
+ ctx->set_search_paths(vector_of_paths);
+ } catch( const std::exception& )
+ {
}
-
- path_count = count;
}
-/* just a couple of helper functions that lets other functions
- access the otherwise private search path */
-const char * const *proj_get_searchpath(void) {
- return (const char * const *)search_path;
-}
+/************************************************************************/
+/* pj_set_searchpath() */
+/* */
+/* Path control for callers that can't practically provide */
+/* pj_set_finder() style callbacks. Call with (0,NULL) as args */
+/* to clear the searchpath set. */
+/************************************************************************/
-int proj_get_path_count(void) {
- return path_count;
+void pj_set_searchpath ( int count, const char **path )
+{
+ proj_context_set_search_paths( nullptr, count, const_cast<const char* const*>(path) );
}
+
/************************************************************************/
/* pj_open_lib_ex() */
/************************************************************************/
@@ -112,16 +152,19 @@ static PAFile
pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
char* out_full_filename, size_t out_full_filename_size) {
char fname[MAX_PATH_FILENAME+1];
- const char *sysname;
+ const char *sysname = nullptr;
PAFile fid;
int n = 0;
- int i;
#ifdef WIN32
static const char dir_chars[] = "/\\";
#else
static const char dir_chars[] = "/";
#endif
+ if( ctx == nullptr ) {
+ ctx = pj_get_default_ctx();
+ }
+
if( out_full_filename != nullptr && out_full_filename_size > 0 )
out_full_filename[0] = '\0';
@@ -148,8 +191,11 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
sysname = name;
/* or try to use application provided file finder */
- else if( pj_finder != nullptr && pj_finder( name ) != nullptr )
- sysname = pj_finder( name );
+ else if( ctx && ctx->file_finder != nullptr && (sysname = ctx->file_finder( ctx, name, ctx->file_finder_user_data )) != nullptr )
+ ;
+
+ else if( ctx && ctx->file_finder_legacy != nullptr && (sysname = ctx->file_finder_legacy( name )) != nullptr )
+ ;
/* or is environment PROJ_LIB defined */
else if ((sysname = getenv("PROJ_LIB")) || (sysname = proj_lib_name)) {
@@ -176,16 +222,19 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
}
/* If none of those work and we have a search path, try it */
- if (!fid && path_count > 0)
+ std::string tmp;
+ if (!fid && ctx && !ctx->search_paths.empty() )
{
- for (i = 0; fid == nullptr && i < path_count; i++)
- {
- if( strlen(search_path[i]) + 1 + strlen(name) + 1 <= sizeof(fname) )
- {
- sprintf(fname, "%s%c%s", search_path[i], DIR_CHAR, name);
- sysname = fname;
+ for( const auto& path: ctx->search_paths ) {
+ try {
+ tmp = path + DIR_CHAR + name;
+ sysname = tmp.c_str();
fid = pj_ctx_fopen(ctx, sysname, mode);
+ } catch( const std::exception& )
+ {
}
+ if( fid )
+ break;
}
if (fid)
{
diff --git a/src/proj.h b/src/proj.h
index ef14f237..214bad17 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -336,6 +336,12 @@ typedef struct projCtx_t PJ_CONTEXT;
PJ_CONTEXT PROJ_DLL *proj_context_create (void);
PJ_CONTEXT PROJ_DLL *proj_context_destroy (PJ_CONTEXT *ctx);
+/** Callback to resolve a filename to a full path */
+typedef const char* (*proj_file_finder) (PJ_CONTEXT *ctx, const char*, void* user_data);
+
+void PROJ_DLL proj_context_set_file_finder(PJ_CONTEXT *ctx, proj_file_finder finder, void* user_data);
+void PROJ_DLL proj_context_set_search_paths(PJ_CONTEXT *ctx, int count_paths, const char* const* paths);
+
void PROJ_DLL proj_context_use_proj4_init_rules(PJ_CONTEXT *ctx, int enable);
int PROJ_DLL proj_context_get_use_proj4_init_rules(PJ_CONTEXT *ctx, int from_legacy_code_path);
diff --git a/src/proj_internal.h b/src/proj_internal.h
index 31365bce..bbadb376 100644
--- a/src/proj_internal.h
+++ b/src/proj_internal.h
@@ -228,9 +228,6 @@ char *pj_make_args (size_t argc, char **argv);
/* Lowest level: Minimum support for fileapi */
void proj_fileapi_set (PJ *P, void *fileapi);
-const char * const *proj_get_searchpath(void);
-int proj_get_path_count(void);
-
typedef struct { double r, i; } COMPLEX;
/* Forward declarations and typedefs for stuff needed inside the PJ object */
@@ -653,12 +650,21 @@ struct projCtx_t {
int use_proj4_init_rules = -1; /* -1 = unknown, 0 = no, 1 = yes */
int epsg_file_exists = -1; /* -1 = unknown, 0 = no, 1 = yes */
+ std::vector<std::string> search_paths{};
+ const char **c_compat_paths = nullptr; // same, but for projinfo usage
+
+ const char* (*file_finder_legacy) (const char*) = nullptr; // Only for proj_api compat. To remove once it is removed
+ const char* (*file_finder) (PJ_CONTEXT *, const char*, void* user_data) = nullptr;
+ void* file_finder_user_data = nullptr;
+
projCtx_t() = default;
projCtx_t(const projCtx_t&);
~projCtx_t();
projCtx_t& operator= (const projCtx_t&) = delete;
+ void set_search_paths(const std::vector<std::string>& search_paths_in);
+
static projCtx_t createDefault();
};