diff --git a/include/proj/internal/io_internal.hpp b/include/proj/internal/io_internal.hpp index f614fc67b4..b7f514d582 100644 --- a/include/proj/internal/io_internal.hpp +++ b/include/proj/internal/io_internal.hpp @@ -168,6 +168,9 @@ NS_PROJ_END struct projCppContext { NS_PROJ::io::DatabaseContextNNPtr databaseContext; std::string lastUOMName_{}; + std::string lastGridFullName_{}; + std::string lastGridPackageName_{}; + std::string lastGridUrl_{}; explicit projCppContext(PJ_CONTEXT *ctx, const char *dbPath = nullptr, const char *const *auxDbPaths = nullptr) diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt index fe217812f8..6bdef68e7a 100644 --- a/scripts/reference_exported_symbols.txt +++ b/scripts/reference_exported_symbols.txt @@ -915,6 +915,7 @@ proj_get_prime_meridian proj_get_source_crs proj_get_target_crs proj_get_type +proj_grid_get_info_from_database proj_grid_info proj_identify proj_info diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index 5d2216e80e..1e3a331cbb 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -626,6 +626,65 @@ int proj_uom_get_info_from_database(PJ_CONTEXT *ctx, const char *auth_name, // --------------------------------------------------------------------------- +/** \brief Get information for a grid from a database lookup. + * + * @param ctx Context, or NULL for default context. + * @param grid_name Grid name (must not be NULL) + * @param out_full_name Pointer to a string value to store the grid full + * filename. or NULL + * @param out_package_name Pointer to a string value to store the package name + * where + * the grid might be found. or NULL + * @param out_url Pointer to a string value to store the grid URL or the + * package URL where the grid might be found. or NULL + * @param out_direct_download Pointer to a int (boolean) value to store whether + * *out_url can be downloaded directly. or NULL + * @param out_open_license Pointer to a int (boolean) value to store whether + * the grid is released with an open license. or NULL + * @param out_available Pointer to a int (boolean) value to store whether the + * grid is available at runtime. or NULL + * @return TRUE in case of success. + */ +int PROJ_DLL proj_grid_get_info_from_database( + PJ_CONTEXT *ctx, const char *grid_name, const char **out_full_name, + const char **out_package_name, const char **out_url, + int *out_direct_download, int *out_open_license, int *out_available) { + assert(grid_name); + SANITIZE_CTX(ctx); + try { + auto db_context = getDBcontext(ctx); + bool direct_download; + bool open_license; + bool available; + if (!db_context->lookForGridInfo( + grid_name, ctx->cpp_context->lastGridFullName_, + ctx->cpp_context->lastGridPackageName_, + ctx->cpp_context->lastGridUrl_, direct_download, open_license, + available)) + return false; + + if (out_full_name) + *out_full_name = ctx->cpp_context->lastGridFullName_.c_str(); + if (out_package_name) + *out_package_name = ctx->cpp_context->lastGridPackageName_.c_str(); + if (out_url) + *out_url = ctx->cpp_context->lastGridUrl_.c_str(); + if (out_direct_download) + *out_direct_download = direct_download ? 1 : 0; + if (out_open_license) + *out_open_license = open_license ? 1 : 0; + if (out_available) + *out_available = available ? 1 : 0; + + return true; + } catch (const std::exception &e) { + proj_log_error(ctx, __FUNCTION__, e.what()); + } + return false; +} + +// --------------------------------------------------------------------------- + /** \brief Return GeodeticCRS that use the specified datum. * * @param ctx Context, or NULL for default context. diff --git a/src/proj.h b/src/proj.h index a412f2669d..a39d3150e9 100644 --- a/src/proj.h +++ b/src/proj.h @@ -787,6 +787,15 @@ int PROJ_DLL proj_uom_get_info_from_database(PJ_CONTEXT *ctx, double *out_conv_factor, const char **out_category); +int PROJ_DLL proj_grid_get_info_from_database(PJ_CONTEXT *ctx, + const char *grid_name, + const char **out_full_name, + const char **out_package_name, + const char **out_url, + int *out_direct_download, + int *out_open_license, + int *out_available); + PJ PROJ_DLL *proj_clone(PJ_CONTEXT *ctx, const PJ *obj); PJ_OBJ_LIST PROJ_DLL *proj_create_from_name(PJ_CONTEXT *ctx, diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index b9ea0bd5c5..2e6ea2c78b 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -3011,6 +3011,37 @@ TEST_F(CApi, proj_uom_get_info_from_database) { // --------------------------------------------------------------------------- +TEST_F(CApi, proj_grid_get_info_from_database) { + { + EXPECT_FALSE(proj_grid_get_info_from_database(m_ctxt, "xxx", nullptr, + nullptr, nullptr, nullptr, + nullptr, nullptr)); + } + { + EXPECT_TRUE(proj_grid_get_info_from_database( + m_ctxt, "GDA94_GDA2020_conformal.gsb", nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr)); + } + { + const char *name = nullptr; + const char *package_name = nullptr; + const char *url = nullptr; + int direct_download = 0; + int open_license = 0; + int available = 0; + EXPECT_TRUE(proj_grid_get_info_from_database( + m_ctxt, "GDA94_GDA2020_conformal.gsb", &name, &package_name, &url, + &direct_download, &open_license, &available)); + ASSERT_NE(name, nullptr); + ASSERT_NE(package_name, nullptr); + ASSERT_NE(url, nullptr); + EXPECT_EQ(direct_download, 1); + EXPECT_EQ(open_license, 1); + } +} + +// --------------------------------------------------------------------------- + TEST_F(CApi, proj_create_cartesian_2D_cs) { { auto cs = proj_create_cartesian_2D_cs(