aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKristian Evers <kristianevers@gmail.com>2019-01-09 23:55:39 +0100
committerGitHub <noreply@github.com>2019-01-09 23:55:39 +0100
commit763ff547aea5e1013b49254b62fc06060eccfaaf (patch)
treedaf7a4e66059e2021a398bc80e93a120a1147bad /src
parent6d5924842035ae6b5af8a6685f5c531e667c7f18 (diff)
parent03b8e99d388013558b1a2ec02a82af4763b26b34 (diff)
downloadPROJ-763ff547aea5e1013b49254b62fc06060eccfaaf.tar.gz
PROJ-763ff547aea5e1013b49254b62fc06060eccfaaf.zip
Merge pull request #1218 from rouault/search_path
Add API in proj.h to set a file finder callback and search paths; support multiple directories in PROJ_LIB
Diffstat (limited to 'src')
-rw-r--r--src/4D_api.cpp26
-rw-r--r--src/ctx.cpp115
-rw-r--r--src/internal.cpp2
-rw-r--r--src/iso19111/c_api.cpp4
-rw-r--r--src/log.cpp2
-rw-r--r--src/open_lib.cpp297
-rw-r--r--src/proj.h6
-rw-r--r--src/proj_internal.h36
8 files changed, 299 insertions, 189 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 195f3b7f..005070b0 100644
--- a/src/ctx.cpp
+++ b/src/ctx.cpp
@@ -29,12 +29,10 @@
#include <stdlib.h>
#include <string.h>
+#include <new>
+
#include "proj_experimental.h"
#include "proj_internal.h"
-#include "proj_internal.h"
-
-static projCtx_t default_context;
-static volatile int default_context_initialized = 0;
/************************************************************************/
/* pj_get_ctx() */
@@ -81,61 +79,90 @@ void proj_assign_context( PJ* pj, PJ_CONTEXT* ctx )
}
/************************************************************************/
-/* pj_get_default_ctx() */
+/* createDefault() */
/************************************************************************/
-projCtx pj_get_default_ctx()
-
+projCtx_t projCtx_t::createDefault()
{
- /* If already initialized, don't bother locking */
- if( default_context_initialized )
- return &default_context;
-
- pj_acquire_lock();
+ projCtx_t ctx;
+ ctx.debug_level = PJ_LOG_NONE;
+ ctx.logger = pj_stderr_logger;
+ ctx.fileapi = pj_get_default_fileapi();
- /* Ask again, since it may have been initialized in another thread */
- if( !default_context_initialized )
+ if( getenv("PROJ_DEBUG") != nullptr )
{
- default_context.last_errno = 0;
- default_context.debug_level = PJ_LOG_NONE;
- default_context.logger = pj_stderr_logger;
- default_context.app_data = nullptr;
- default_context.fileapi = pj_get_default_fileapi();
- default_context.cpp_context = nullptr;
- default_context.use_proj4_init_rules = -1;
- default_context.epsg_file_exists = -1;
-
- if( getenv("PROJ_DEBUG") != nullptr )
- {
- if( atoi(getenv("PROJ_DEBUG")) >= -PJ_LOG_DEBUG_MINOR )
- default_context.debug_level = atoi(getenv("PROJ_DEBUG"));
- else
- default_context.debug_level = PJ_LOG_DEBUG_MINOR;
+ if( atoi(getenv("PROJ_DEBUG")) >= -PJ_LOG_DEBUG_MINOR )
+ ctx.debug_level = atoi(getenv("PROJ_DEBUG"));
+ else
+ ctx.debug_level = PJ_LOG_DEBUG_MINOR;
+ }
+ return ctx;
+}
+
+/************************************************************************/
+/* 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();
}
- default_context_initialized = 1;
}
+}
- pj_release_lock();
+/************************************************************************/
+/* projCtx_t(const projCtx_t& other) */
+/************************************************************************/
+projCtx_t::projCtx_t(const projCtx_t& other)
+{
+ debug_level = other.debug_level;
+ logger = other.logger;
+ 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;
+}
+
+/************************************************************************/
+/* pj_get_default_ctx() */
+/************************************************************************/
+
+projCtx pj_get_default_ctx()
+
+{
+ // C++11 rules guarantee a thread-safe instanciation.
+ static projCtx_t default_context(projCtx_t::createDefault());
return &default_context;
}
/************************************************************************/
+/* ~projCtx_t() */
+/************************************************************************/
+
+projCtx_t::~projCtx_t()
+{
+ delete[] c_compat_paths;
+ proj_context_delete_cpp_context(cpp_context);
+}
+
+/************************************************************************/
/* pj_ctx_alloc() */
/************************************************************************/
projCtx pj_ctx_alloc()
{
- projCtx ctx = (projCtx_t *) malloc(sizeof(projCtx_t));
- if (nullptr==ctx)
- return nullptr;
- memcpy( ctx, pj_get_default_ctx(), sizeof(projCtx_t) );
- ctx->last_errno = 0;
- ctx->cpp_context = nullptr;
- ctx->use_proj4_init_rules = -1;
-
- return ctx;
+ return new (std::nothrow) projCtx_t(*pj_get_default_ctx());
}
/************************************************************************/
@@ -145,8 +172,7 @@ projCtx pj_ctx_alloc()
void pj_ctx_free( projCtx ctx )
{
- proj_context_delete_cpp_context( ctx->cpp_context );
- pj_dealloc( ctx );
+ delete ctx;
}
/************************************************************************/
@@ -210,7 +236,7 @@ void pj_ctx_set_app_data( projCtx ctx, void *new_app_data )
{
if (nullptr==ctx)
return;
- ctx->app_data = new_app_data;
+ ctx->logger_app_data = new_app_data;
}
/************************************************************************/
@@ -222,7 +248,7 @@ void *pj_ctx_get_app_data( projCtx ctx )
{
if (nullptr==ctx)
return nullptr;
- return ctx->app_data;
+ return ctx->logger_app_data;
}
/************************************************************************/
@@ -248,3 +274,4 @@ projFileAPI *pj_ctx_get_fileapi( projCtx ctx )
return nullptr;
return ctx->fileapi;
}
+
diff --git a/src/internal.cpp b/src/internal.cpp
index f774cad6..fbc7c9a1 100644
--- a/src/internal.cpp
+++ b/src/internal.cpp
@@ -449,7 +449,7 @@ void proj_log_func (PJ_CONTEXT *ctx, void *app_data, PJ_LOG_FUNCTION logf) {
pj_get_default_ctx ();
if (nullptr==ctx)
return;
- ctx->app_data = app_data;
+ ctx->logger_app_data = app_data;
if (nullptr!=logf)
ctx->logger = logf;
}
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index 5717a76a..d13c33c7 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -74,7 +74,7 @@ static void PROJ_NO_INLINE proj_log_error(PJ_CONTEXT *ctx, const char *function,
std::string msg(function);
msg += ": ";
msg += text;
- ctx->logger(ctx->app_data, PJ_LOG_ERROR, msg.c_str());
+ ctx->logger(ctx->logger_app_data, PJ_LOG_ERROR, msg.c_str());
}
// ---------------------------------------------------------------------------
@@ -84,7 +84,7 @@ static void PROJ_NO_INLINE proj_log_debug(PJ_CONTEXT *ctx, const char *function,
std::string msg(function);
msg += ": ";
msg += text;
- ctx->logger(ctx->app_data, PJ_LOG_DEBUG, msg.c_str());
+ ctx->logger(ctx->logger_app_data, PJ_LOG_DEBUG, msg.c_str());
}
// ---------------------------------------------------------------------------
diff --git a/src/log.cpp b/src/log.cpp
index 4c15772b..3cc10cfd 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -74,7 +74,7 @@ void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args )
/* we should use vsnprintf where available once we add configure detect.*/
vsprintf( msg_buf, fmt, args );
- ctx->logger( ctx->app_data, level, msg_buf );
+ ctx->logger( ctx->logger_app_data, level, msg_buf );
free( msg_buf );
}
diff --git a/src/open_lib.cpp b/src/open_lib.cpp
index f4fa313f..510704e9 100644
--- a/src/open_lib.cpp
+++ b/src/open_lib.cpp
@@ -30,18 +30,20 @@
#define PJ_LIB__
+#ifndef FROM_PROJ_CPP
+#define FROM_PROJ_CPP
+#endif
+
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "proj_internal.h"
+#include "proj/internal/internal.hpp"
+
#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 +58,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() */
/************************************************************************/
@@ -111,83 +157,73 @@ int proj_get_path_count(void) {
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;
- PAFile fid;
- int n = 0;
- int i;
+ try {
+ std::string fname;
+ const char *sysname = nullptr;
+ PAFile fid = nullptr;
#ifdef WIN32
- static const char dir_chars[] = "/\\";
+ static const char dir_chars[] = "/\\";
+ const char dirSeparator = ';';
#else
- static const char dir_chars[] = "/";
+ static const char dir_chars[] = "/";
+ const char dirSeparator = ':';
#endif
- if( out_full_filename != nullptr && out_full_filename_size > 0 )
- out_full_filename[0] = '\0';
-
- /* check if ~/name */
- if (*name == '~' && strchr(dir_chars,name[1]) )
- if ((sysname = getenv("HOME")) != nullptr) {
- if( strlen(sysname) + 1 + strlen(name) + 1 > sizeof(fname) )
- {
- return nullptr;
- }
- (void)strcpy(fname, sysname);
- fname[n = (int)strlen(fname)] = DIR_CHAR;
- fname[++n] = '\0';
- (void)strcpy(fname+n, name + 1);
- sysname = fname;
- } else
- return nullptr;
-
- /* or fixed path: /name, ./name or ../name */
- else if (strchr(dir_chars,*name)
- || (*name == '.' && strchr(dir_chars,name[1]))
- || (!strncmp(name, "..", 2) && strchr(dir_chars,name[2]))
- || (name[1] == ':' && strchr(dir_chars,name[2])) )
- sysname = name;
-
- /* or try to use application provided file finder */
- else if( pj_finder != nullptr && pj_finder( name ) != nullptr )
- sysname = pj_finder( name );
-
- /* or is environment PROJ_LIB defined */
- else if ((sysname = getenv("PROJ_LIB")) || (sysname = proj_lib_name)) {
- if( strlen(sysname) + 1 + strlen(name) + 1 > sizeof(fname) )
- {
- return nullptr;
+ if( ctx == nullptr ) {
+ ctx = pj_get_default_ctx();
}
- (void)strcpy(fname, sysname);
- fname[n = (int)strlen(fname)] = DIR_CHAR;
- fname[++n] = '\0';
- (void)strcpy(fname+n, name);
- sysname = fname;
- } else /* just try it bare bones */
- sysname = name;
-
- if ((fid = pj_ctx_fopen(ctx, sysname, mode)) != nullptr)
- {
+
if( out_full_filename != nullptr && out_full_filename_size > 0 )
- {
- strncpy(out_full_filename, sysname, out_full_filename_size);
- out_full_filename[out_full_filename_size-1] = '\0';
- }
- errno = 0;
- }
+ out_full_filename[0] = '\0';
- /* If none of those work and we have a search path, try it */
- if (!fid && path_count > 0)
- {
- 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;
+ /* check if ~/name */
+ if (*name == '~' && strchr(dir_chars,name[1]) )
+ if ((sysname = getenv("HOME")) != nullptr) {
+ fname = sysname;
+ fname += DIR_CHAR;
+ fname += name;
+ sysname = fname.c_str();
+ } else
+ return nullptr;
+
+ /* or fixed path: /name, ./name or ../name */
+ else if (strchr(dir_chars,*name)
+ || (*name == '.' && strchr(dir_chars,name[1]))
+ || (!strncmp(name, "..", 2) && strchr(dir_chars,name[2]))
+ || (name[1] == ':' && strchr(dir_chars,name[2])) )
+ sysname = name;
+
+ /* or try to use application provided file finder */
+ 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")) != nullptr) {
+
+ auto paths = NS_PROJ::internal::split(std::string(sysname), dirSeparator);
+ for( const auto& path: paths ) {
+ fname = path;
+ fname += DIR_CHAR;
+ fname += name;
+ sysname = fname.c_str();
fid = pj_ctx_fopen(ctx, sysname, mode);
+ if( fid )
+ break;
}
- }
- if (fid)
+
+ /* or hardcoded path */
+ } else if ((sysname = proj_lib_name) != nullptr) {
+ fname = sysname;
+ fname += DIR_CHAR;
+ fname += name;
+ sysname = fname.c_str();
+ } else /* just try it bare bones */
+ sysname = name;
+
+ if ( fid != nullptr || (fid = pj_ctx_fopen(ctx, sysname, mode)) != nullptr)
{
if( out_full_filename != nullptr && out_full_filename_size > 0 )
{
@@ -196,17 +232,52 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
}
errno = 0;
}
- }
- if( ctx->last_errno == 0 && errno != 0 )
- pj_ctx_set_errno( ctx, errno );
+ /* If none of those work and we have a search path, try it */
+ if (!fid && ctx && !ctx->search_paths.empty() )
+ {
+ for( const auto& path: ctx->search_paths ) {
+ try {
+ fname = path;
+ fname += DIR_CHAR;
+ fname += name;
+ sysname = fname.c_str();
+ fid = pj_ctx_fopen(ctx, sysname, mode);
+ } catch( const std::exception& )
+ {
+ }
+ if( fid )
+ break;
+ }
+ if (fid)
+ {
+ if( out_full_filename != nullptr && out_full_filename_size > 0 )
+ {
+ strncpy(out_full_filename, sysname, out_full_filename_size);
+ out_full_filename[out_full_filename_size-1] = '\0';
+ }
+ errno = 0;
+ }
+ }
+
+ if( ctx->last_errno == 0 && errno != 0 )
+ pj_ctx_set_errno( ctx, errno );
- pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
- "pj_open_lib(%s): call fopen(%s) - %s",
- name, sysname,
- fid == nullptr ? "failed" : "succeeded" );
+ pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
+ "pj_open_lib(%s): call fopen(%s) - %s",
+ name, sysname,
+ fid == nullptr ? "failed" : "succeeded" );
- return(fid);
+ return(fid);
+ }
+ catch( const std::exception& ) {
+
+ pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
+ "pj_open_lib(%s): out of memory",
+ name );
+
+ return nullptr;
+ }
}
/************************************************************************/
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 63e10407..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 */
@@ -644,14 +641,31 @@ struct projCppContext;
/* proj thread context */
struct projCtx_t {
- int last_errno;
- int debug_level;
- void (*logger)(void *, int, const char *);
- void *app_data;
- struct projFileAPI_t *fileapi;
- struct projCppContext* cpp_context; /* internal context for C++ code */
- int use_proj4_init_rules; /* -1 = unknown, 0 = no, 1 = yes */
- int epsg_file_exists; /* -1 = unknown, 0 = no, 1 = yes */
+ int last_errno = 0;
+ int debug_level = 0;
+ void (*logger)(void *, int, const char *) = nullptr;
+ void *logger_app_data = nullptr;
+ struct projFileAPI_t *fileapi = nullptr;
+ struct projCppContext* cpp_context = nullptr; /* internal context for C++ code */
+ 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();
};
/* Generate pj_list external or make list from include file */