diff options
| author | Alan D. Snow <alansnow21@gmail.com> | 2020-08-19 08:02:42 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-19 15:02:42 +0200 |
| commit | 84713021edf688c9cf157562d34388583325aa45 (patch) | |
| tree | 6a1694de8df49fb68a66e74c02e5f8750a0c0e78 | |
| parent | 62ad09fe02c4a67e727822134768e4ebe6c8cde4 (diff) | |
| download | PROJ-84713021edf688c9cf157562d34388583325aa45.tar.gz PROJ-84713021edf688c9cf157562d34388583325aa45.zip | |
Clone projCppContext context when copying projCtx_t (#2324)
| -rw-r--r-- | include/proj/internal/io_internal.hpp | 2 | ||||
| -rw-r--r-- | src/ctx.cpp | 7 | ||||
| -rw-r--r-- | src/iso19111/c_api.cpp | 12 | ||||
| -rw-r--r-- | test/unit/test_c_api.cpp | 64 |
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"); |
