1 /******************************************************************************
2 * Project: PROJ.4
3 * Purpose: Implementation of the projCtx thread context object.
4 * Author: Frank Warmerdam, warmerdam@pobox.com
5 *
6 ******************************************************************************
7 * Copyright (c) 2010, Frank Warmerdam
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *****************************************************************************/
27 #ifndef FROM_PROJ_CPP
28 #define FROM_PROJ_CPP
29 #endif
30
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <new>
36
37 #include "proj_experimental.h"
38 #include "proj_internal.h"
39 #include "filemanager.hpp"
40 #include "proj/internal/io_internal.hpp"
41
42 /************************************************************************/
43 /* pj_get_ctx() */
44 /************************************************************************/
45
pj_get_ctx(projPJ pj)46 projCtx pj_get_ctx( projPJ pj )
47
48 {
49 if (nullptr==pj)
50 return pj_get_default_ctx ();
51 if (nullptr==pj->ctx)
52 return pj_get_default_ctx ();
53 return pj->ctx;
54 }
55
56 /************************************************************************/
57 /* pj_set_ctx() */
58 /* */
59 /* Note we do not deallocate the old context! */
60 /************************************************************************/
61
pj_set_ctx(projPJ pj,projCtx ctx)62 void pj_set_ctx( projPJ pj, projCtx ctx )
63
64 {
65 if (pj==nullptr)
66 return;
67 pj->ctx = ctx;
68 if( pj->reassign_context )
69 {
70 pj->reassign_context(pj, ctx);
71 }
72 for( const auto &alt: pj->alternativeCoordinateOperations )
73 {
74 pj_set_ctx(alt.pj, ctx);
75 }
76 }
77
78 /************************************************************************/
79 /* proj_assign_context() */
80 /************************************************************************/
81
82 /** \brief Re-assign a context to a PJ* object.
83 *
84 * This may be useful if the PJ* has been created with a context that is
85 * thread-specific, and is later used in another thread. In that case,
86 * the user may want to assign another thread-specific context to the
87 * object.
88 */
proj_assign_context(PJ * pj,PJ_CONTEXT * ctx)89 void proj_assign_context( PJ* pj, PJ_CONTEXT* ctx )
90 {
91 pj_set_ctx( pj, ctx );
92 }
93
94 /************************************************************************/
95 /* createDefault() */
96 /************************************************************************/
97
createDefault()98 projCtx_t projCtx_t::createDefault()
99 {
100 projCtx_t ctx;
101 ctx.debug_level = PJ_LOG_NONE;
102 ctx.logger = pj_stderr_logger;
103 ctx.fileapi_legacy = pj_get_default_fileapi();
104 NS_PROJ::FileManager::fillDefaultNetworkInterface(&ctx);
105
106 if( getenv("PROJ_DEBUG") != nullptr )
107 {
108 if( atoi(getenv("PROJ_DEBUG")) >= -PJ_LOG_DEBUG_MINOR )
109 ctx.debug_level = atoi(getenv("PROJ_DEBUG"));
110 else
111 ctx.debug_level = PJ_LOG_DEBUG_MINOR;
112 }
113 return ctx;
114 }
115
116 /**************************************************************************/
117 /* get_cpp_context() */
118 /**************************************************************************/
119
get_cpp_context()120 projCppContext* projCtx_t::get_cpp_context()
121 {
122 if (cpp_context == nullptr) {
123 cpp_context = new projCppContext(this);
124 }
125 return cpp_context;
126 }
127
128
129 /**************************************************************************/
130 /* safeAutoCloseDbIfNeeded() */
131 /**************************************************************************/
132
safeAutoCloseDbIfNeeded()133 void projCtx_t::safeAutoCloseDbIfNeeded()
134 {
135 if (cpp_context) {
136 cpp_context->autoCloseDbIfNeeded();
137 }
138 }
139
140 /************************************************************************/
141 /* set_search_paths() */
142 /************************************************************************/
143
set_search_paths(const std::vector<std::string> & search_paths_in)144 void projCtx_t::set_search_paths(const std::vector<std::string>& search_paths_in )
145 {
146 search_paths = search_paths_in;
147 delete[] c_compat_paths;
148 c_compat_paths = nullptr;
149 if( !search_paths.empty() ) {
150 c_compat_paths = new const char*[search_paths.size()];
151 for( size_t i = 0; i < search_paths.size(); ++i ) {
152 c_compat_paths[i] = search_paths[i].c_str();
153 }
154 }
155 }
156
157 /**************************************************************************/
158 /* set_ca_bundle_path() */
159 /**************************************************************************/
160
set_ca_bundle_path(const std::string & ca_bundle_path_in)161 void projCtx_t::set_ca_bundle_path(const std::string& ca_bundle_path_in)
162 {
163 ca_bundle_path = ca_bundle_path_in;
164 }
165
166 /************************************************************************/
167 /* projCtx_t(const projCtx_t& other) */
168 /************************************************************************/
169
projCtx_t(const projCtx_t & other)170 projCtx_t::projCtx_t(const projCtx_t& other) :
171 debug_level(other.debug_level),
172 logger(other.logger),
173 logger_app_data(other.logger_app_data),
174 fileapi_legacy(other.fileapi_legacy),
175 cpp_context(other.cpp_context ? other.cpp_context->clone(this) : nullptr),
176 use_proj4_init_rules(other.use_proj4_init_rules),
177 epsg_file_exists(other.epsg_file_exists),
178 ca_bundle_path(other.ca_bundle_path),
179 env_var_proj_lib(other.env_var_proj_lib),
180 file_finder_legacy(other.file_finder_legacy),
181 file_finder(other.file_finder),
182 file_finder_user_data(other.file_finder_user_data),
183 custom_sqlite3_vfs_name(other.custom_sqlite3_vfs_name),
184 user_writable_directory(other.user_writable_directory),
185 // BEGIN ini file settings
186 iniFileLoaded(other.iniFileLoaded),
187 endpoint(other.endpoint),
188 networking(other.networking),
189 gridChunkCache(other.gridChunkCache),
190 defaultTmercAlgo(other.defaultTmercAlgo)
191 // END ini file settings
192 {
193 set_search_paths(other.search_paths);
194 }
195
196 /************************************************************************/
197 /* pj_get_default_ctx() */
198 /************************************************************************/
199
pj_get_default_ctx()200 projCtx pj_get_default_ctx()
201
202 {
203 // C++11 rules guarantee a thread-safe instantiation.
204 static projCtx_t default_context(projCtx_t::createDefault());
205 return &default_context;
206 }
207
208 /************************************************************************/
209 /* ~projCtx_t() */
210 /************************************************************************/
211
~projCtx_t()212 projCtx_t::~projCtx_t()
213 {
214 delete[] c_compat_paths;
215 proj_context_delete_cpp_context(cpp_context);
216 }
217
218 /************************************************************************/
219 /* pj_ctx_alloc() */
220 /************************************************************************/
221
pj_ctx_alloc()222 projCtx pj_ctx_alloc()
223
224 {
225 return new (std::nothrow) projCtx_t(*pj_get_default_ctx());
226 }
227
228 /************************************************************************/
229 /* proj_context_clone() */
230 /* Create a new context based on a custom context */
231 /************************************************************************/
232
proj_context_clone(PJ_CONTEXT * ctx)233 PJ_CONTEXT *proj_context_clone (PJ_CONTEXT *ctx)
234 {
235 if (nullptr==ctx)
236 return pj_ctx_alloc ();
237
238 return new (std::nothrow) projCtx_t(*ctx);
239 }
240
241 /************************************************************************/
242 /* pj_ctx_free() */
243 /************************************************************************/
244
pj_ctx_free(projCtx ctx)245 void pj_ctx_free( projCtx ctx )
246
247 {
248 delete ctx;
249 }
250
251 /************************************************************************/
252 /* pj_ctx_get_errno() */
253 /************************************************************************/
254
pj_ctx_get_errno(projCtx ctx)255 int pj_ctx_get_errno( projCtx ctx )
256
257 {
258 if (nullptr==ctx)
259 return pj_get_default_ctx ()->last_errno;
260 return ctx->last_errno;
261 }
262
263 /************************************************************************/
264 /* pj_ctx_set_errno() */
265 /* */
266 /* Also sets the global errno */
267 /************************************************************************/
268
pj_ctx_set_errno(projCtx ctx,int new_errno)269 void pj_ctx_set_errno( projCtx ctx, int new_errno )
270
271 {
272 ctx->last_errno = new_errno;
273 if( new_errno == 0 )
274 return;
275 errno = new_errno;
276 pj_errno = new_errno;
277 }
278
279 /************************************************************************/
280 /* pj_ctx_set_debug() */
281 /************************************************************************/
282
pj_ctx_set_debug(projCtx ctx,int new_debug)283 void pj_ctx_set_debug( projCtx ctx, int new_debug )
284
285 {
286 if (nullptr==ctx)
287 return;
288 ctx->debug_level = new_debug;
289 }
290
291 /************************************************************************/
292 /* pj_ctx_set_logger() */
293 /************************************************************************/
294
pj_ctx_set_logger(projCtx ctx,void (* new_logger)(void *,int,const char *))295 void pj_ctx_set_logger( projCtx ctx, void (*new_logger)(void*,int,const char*) )
296
297 {
298 if (nullptr==ctx)
299 return;
300 ctx->logger = new_logger;
301 }
302
303 /************************************************************************/
304 /* pj_ctx_set_app_data() */
305 /************************************************************************/
306
pj_ctx_set_app_data(projCtx ctx,void * new_app_data)307 void pj_ctx_set_app_data( projCtx ctx, void *new_app_data )
308
309 {
310 if (nullptr==ctx)
311 return;
312 ctx->logger_app_data = new_app_data;
313 }
314
315 /************************************************************************/
316 /* pj_ctx_get_app_data() */
317 /************************************************************************/
318
pj_ctx_get_app_data(projCtx ctx)319 void *pj_ctx_get_app_data( projCtx ctx )
320
321 {
322 if (nullptr==ctx)
323 return nullptr;
324 return ctx->logger_app_data;
325 }
326