aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/proj/internal/io_internal.hpp2
-rw-r--r--src/ctx.cpp7
-rw-r--r--src/iso19111/c_api.cpp12
-rw-r--r--test/unit/test_c_api.cpp64
4 files changed, 85 insertions, 0 deletions
diff --git a/include/proj/internal/io_internal.hpp b/include/proj/internal/io_internal.hpp
index 617dffab..31dd70df 100644
--- a/include/proj/internal/io_internal.hpp
+++ b/include/proj/internal/io_internal.hpp
@@ -191,6 +191,8 @@ struct projCppContext {
explicit projCppContext(PJ_CONTEXT *ctx, const char *dbPath = nullptr,
const std::vector<std::string> &auxDbPaths = {});
+ projCppContext* clone(PJ_CONTEXT *ctx) const;
+
// cppcheck-suppress functionStatic
inline const std::string &getDbPath() const { return dbPath_; }
diff --git a/src/ctx.cpp b/src/ctx.cpp
index 1e97e58a..930ae9ea 100644
--- a/src/ctx.cpp
+++ b/src/ctx.cpp
@@ -24,6 +24,9 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
+#ifndef FROM_PROJ_CPP
+#define FROM_PROJ_CPP
+#endif
#include <errno.h>
#include <stdlib.h>
@@ -34,6 +37,7 @@
#include "proj_experimental.h"
#include "proj_internal.h"
#include "filemanager.hpp"
+#include "proj/internal/io_internal.hpp"
/************************************************************************/
/* pj_get_ctx() */
@@ -152,6 +156,9 @@ projCtx_t::projCtx_t(const projCtx_t& other)
file_finder_user_data = other.file_finder_user_data;
networking = other.networking;
ca_bundle_path = other.ca_bundle_path;
+ if (other.cpp_context != nullptr) {
+ cpp_context = other.cpp_context->clone(this);
+ }
}
/************************************************************************/
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index 9219f767..947be058 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -125,6 +125,18 @@ projCppContext::toVector(const char *const *auxDbPaths) {
// ---------------------------------------------------------------------------
+projCppContext* projCppContext::clone(PJ_CONTEXT *ctx) const {
+ projCppContext* newContext = new projCppContext(
+ ctx,
+ getDbPath().c_str(),
+ getAuxDbPaths()
+ );
+ newContext->setAutoCloseDb(getAutoCloseDb());
+ return newContext;
+}
+
+// ---------------------------------------------------------------------------
+
void projCppContext::closeDb() { databaseContext_ = nullptr; }
// ---------------------------------------------------------------------------
diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp
index 4dd2c326..8c9c3dd1 100644
--- a/test/unit/test_c_api.cpp
+++ b/test/unit/test_c_api.cpp
@@ -132,6 +132,17 @@ class CApi : public ::testing::Test {
ObjectKeeper &operator=(const ObjectKeeper &) = delete;
};
+ struct PjContextKeeper {
+ PJ_CONTEXT *m_ctxt = nullptr;
+ explicit PjContextKeeper(PJ_CONTEXT *ctxt)
+ : m_ctxt(ctxt) {}
+ ~PjContextKeeper() { proj_context_destroy(m_ctxt); }
+
+ PjContextKeeper(const PjContextKeeper &) = delete;
+ PjContextKeeper &operator=(const PjContextKeeper &) = delete;
+ };
+
+
struct ContextKeeper {
PJ_OPERATION_FACTORY_CONTEXT *m_op_ctxt = nullptr;
explicit ContextKeeper(PJ_OPERATION_FACTORY_CONTEXT *op_ctxt)
@@ -4038,6 +4049,59 @@ TEST_F(Fixture_proj_context_set_autoclose_database,
// ---------------------------------------------------------------------------
+TEST_F(CApi, proj_context_clone) {
+ auto c_path = proj_context_get_database_path(m_ctxt);
+ ASSERT_TRUE(c_path != nullptr);
+ std::string path(c_path);
+
+ FILE *f = fopen(path.c_str(), "rb");
+ ASSERT_NE(f, nullptr);
+ fseek(f, 0, SEEK_END);
+ auto length = ftell(f);
+ std::string content;
+ content.resize(static_cast<size_t>(length));
+ fseek(f, 0, SEEK_SET);
+ auto read_bytes = fread(&content[0], 1, content.size(), f);
+ ASSERT_EQ(read_bytes, content.size());
+ fclose(f);
+ const char *tempdir = getenv("TEMP");
+ if (!tempdir) {
+ tempdir = getenv("TMP");
+ }
+ if (!tempdir) {
+ tempdir = "/tmp";
+ }
+ std::string tmp_filename(
+ std::string(tempdir) +
+ "/test_proj_context_set_autoclose_database.db");
+ f = fopen(tmp_filename.c_str(), "wb");
+ if (!f) {
+ std::cerr << "Cannot create " << tmp_filename << std::endl;
+ return;
+ }
+ fwrite(content.data(), 1, content.size(), f);
+ fclose(f);
+
+ auto c_default_path = proj_context_get_database_path(nullptr);
+ std::string default_path(c_default_path ? c_default_path: "");
+ EXPECT_TRUE(proj_context_set_database_path(nullptr, tmp_filename.c_str(),
+ nullptr, nullptr));
+
+ PJ_CONTEXT *new_ctx = proj_context_create();
+ EXPECT_TRUE(proj_context_set_database_path(
+ nullptr, default_path.empty() ? nullptr : default_path.c_str(),
+ nullptr, nullptr));
+
+ EXPECT_NE(new_ctx, nullptr);
+ PjContextKeeper keeper_ctxt(new_ctx);
+ auto c_new_path = proj_context_get_database_path(new_ctx);
+ ASSERT_TRUE(c_new_path != nullptr);
+ std::string new_db_path(c_new_path);
+ ASSERT_EQ(new_db_path, tmp_filename);
+}
+
+// ---------------------------------------------------------------------------
+
TEST_F(CApi, proj_create_crs_to_crs_from_pj) {
auto src = proj_create(m_ctxt, "EPSG:4326");