aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/reformat_cpp.sh3
-rw-r--r--src/Makefile.am4
-rw-r--r--src/ctx.cpp25
-rw-r--r--src/fileapi.cpp26
-rw-r--r--src/filemanager.cpp173
-rw-r--r--src/filemanager.hpp68
-rw-r--r--src/lib_proj.cmake2
-rw-r--r--src/open_lib.cpp65
8 files changed, 327 insertions, 39 deletions
diff --git a/scripts/reformat_cpp.sh b/scripts/reformat_cpp.sh
index 899e665f..ca20e0d8 100755
--- a/scripts/reformat_cpp.sh
+++ b/scripts/reformat_cpp.sh
@@ -17,7 +17,8 @@ TOPDIR="$SCRIPT_DIR/.."
for i in "$TOPDIR"/include/proj/*.hpp "$TOPDIR"/include/proj/internal/*.hpp \
"$TOPDIR"/src/iso19111/*.cpp "$TOPDIR"/test/unit/*.cpp "$TOPDIR"/src/apps/projinfo.cpp \
- "$TOPDIR"/src/tracing.cpp "$TOPDIR"/src/grids.hpp "$TOPDIR"/src/grids.cpp; do
+ "$TOPDIR"/src/tracing.cpp "$TOPDIR"/src/grids.hpp "$TOPDIR"/src/grids.cpp \
+ "$TOPDIR"/src/filemanager.hpp "$TOPDIR"/src/filemanager.cpp ; do
if ! echo "$i" | grep -q "lru_cache.hpp"; then
"$SCRIPT_DIR"/reformat.sh "$i";
fi
diff --git a/src/Makefile.am b/src/Makefile.am
index 9a4b3cae..f5cabe5e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -215,7 +215,9 @@ libproj_la_SOURCES = \
tracing.cpp \
\
grids.hpp \
- grids.cpp
+ grids.cpp \
+ filemanager.hpp \
+ filemanager.cpp
# The sed hack is to please MSVC
diff --git a/src/ctx.cpp b/src/ctx.cpp
index 4536582d..da90d4d7 100644
--- a/src/ctx.cpp
+++ b/src/ctx.cpp
@@ -258,28 +258,3 @@ void *pj_ctx_get_app_data( projCtx ctx )
return nullptr;
return ctx->logger_app_data;
}
-
-/************************************************************************/
-/* pj_ctx_set_fileapi() */
-/************************************************************************/
-
-void pj_ctx_set_fileapi( projCtx ctx, projFileAPI *fileapi )
-
-{
- if (nullptr==ctx)
- return;
- ctx->fileapi_legacy = fileapi;
-}
-
-/************************************************************************/
-/* pj_ctx_get_fileapi() */
-/************************************************************************/
-
-projFileAPI *pj_ctx_get_fileapi( projCtx ctx )
-
-{
- if (nullptr==ctx)
- return nullptr;
- return ctx->fileapi_legacy;
-}
-
diff --git a/src/fileapi.cpp b/src/fileapi.cpp
index f39d94bb..70be2502 100644
--- a/src/fileapi.cpp
+++ b/src/fileapi.cpp
@@ -34,6 +34,7 @@
#include "proj.h"
#include "proj_internal.h"
+#include "filemanager.hpp"
static PAFile stdio_fopen(projCtx ctx, const char *filename,
const char *access);
@@ -212,3 +213,28 @@ char *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file)
}
return line;
}
+
+/************************************************************************/
+/* pj_ctx_set_fileapi() */
+/************************************************************************/
+
+void pj_ctx_set_fileapi( projCtx ctx, projFileAPI *fileapi )
+
+{
+ if (nullptr==ctx)
+ return;
+ ctx->fileapi_legacy = fileapi;
+}
+
+/************************************************************************/
+/* pj_ctx_get_fileapi() */
+/************************************************************************/
+
+projFileAPI *pj_ctx_get_fileapi( projCtx ctx )
+
+{
+ if (nullptr==ctx)
+ return nullptr;
+ return ctx->fileapi_legacy;
+}
+
diff --git a/src/filemanager.cpp b/src/filemanager.cpp
new file mode 100644
index 00000000..b6164519
--- /dev/null
+++ b/src/filemanager.cpp
@@ -0,0 +1,173 @@
+/******************************************************************************
+ * Project: PROJ
+ * Purpose: File manager
+ * Author: Even Rouault, <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2019, Even Rouault, <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#include "filemanager.hpp"
+#include "proj_internal.h"
+
+NS_PROJ_START
+
+// ---------------------------------------------------------------------------
+
+File::File() = default;
+
+// ---------------------------------------------------------------------------
+
+File::~File() = default;
+
+// ---------------------------------------------------------------------------
+
+class FileStdio : public File {
+ PJ_CONTEXT *m_ctx;
+ FILE *m_fp;
+
+ FileStdio(const FileStdio &) = delete;
+ FileStdio &operator=(const FileStdio &) = delete;
+
+ protected:
+ FileStdio(PJ_CONTEXT *ctx, FILE *fp) : m_ctx(ctx), m_fp(fp) {}
+
+ public:
+ ~FileStdio() override;
+
+ size_t read(void *buffer, size_t sizeBytes) override;
+ bool seek(unsigned long long offset, int whence = SEEK_SET) override;
+ unsigned long long tell() override;
+
+ static std::unique_ptr<File> open(PJ_CONTEXT *ctx, const char *filename);
+};
+
+// ---------------------------------------------------------------------------
+
+FileStdio::~FileStdio() { fclose(m_fp); }
+
+// ---------------------------------------------------------------------------
+
+size_t FileStdio::read(void *buffer, size_t sizeBytes) {
+ return fread(buffer, 1, sizeBytes, m_fp);
+}
+
+// ---------------------------------------------------------------------------
+
+bool FileStdio::seek(unsigned long long offset, int whence) {
+ // TODO one day: use 64-bit offset compatible API
+ if (offset != static_cast<unsigned long long>(static_cast<long>(offset))) {
+ pj_log(m_ctx, PJ_LOG_ERROR,
+ "Attempt at seeking to a 64 bit offset. Not supported yet");
+ return false;
+ }
+ return fseek(m_fp, static_cast<long>(offset), whence) == 0;
+}
+
+// ---------------------------------------------------------------------------
+
+unsigned long long FileStdio::tell() {
+ // TODO one day: use 64-bit offset compatible API
+ return ftell(m_fp);
+}
+
+// ---------------------------------------------------------------------------
+
+std::unique_ptr<File> FileStdio::open(PJ_CONTEXT *ctx, const char *filename) {
+ auto fp = fopen(filename, "rb");
+ return std::unique_ptr<File>(fp ? new FileStdio(ctx, fp) : nullptr);
+}
+
+// ---------------------------------------------------------------------------
+
+#ifndef REMOVE_LEGACY_SUPPORT
+
+class FileLegacyAdapter : public File {
+ PJ_CONTEXT *m_ctx;
+ PAFile m_fp;
+
+ FileLegacyAdapter(const FileLegacyAdapter &) = delete;
+ FileLegacyAdapter &operator=(const FileLegacyAdapter &) = delete;
+
+ protected:
+ FileLegacyAdapter(PJ_CONTEXT *ctx, PAFile fp) : m_ctx(ctx), m_fp(fp) {}
+
+ public:
+ ~FileLegacyAdapter() override;
+
+ size_t read(void *buffer, size_t sizeBytes) override;
+ bool seek(unsigned long long offset, int whence = SEEK_SET) override;
+ unsigned long long tell() override;
+
+ static std::unique_ptr<File> open(PJ_CONTEXT *ctx, const char *filename);
+};
+
+// ---------------------------------------------------------------------------
+
+FileLegacyAdapter::~FileLegacyAdapter() { pj_ctx_fclose(m_ctx, m_fp); }
+
+// ---------------------------------------------------------------------------
+
+size_t FileLegacyAdapter::read(void *buffer, size_t sizeBytes) {
+ return pj_ctx_fread(m_ctx, buffer, 1, sizeBytes, m_fp);
+}
+
+// ---------------------------------------------------------------------------
+
+bool FileLegacyAdapter::seek(unsigned long long offset, int whence) {
+ if (offset != static_cast<unsigned long long>(static_cast<long>(offset))) {
+ pj_log(m_ctx, PJ_LOG_ERROR,
+ "Attempt at seeking to a 64 bit offset. Not supported yet");
+ return false;
+ }
+ return pj_ctx_fseek(m_ctx, m_fp, static_cast<long>(offset), whence) == 0;
+}
+
+// ---------------------------------------------------------------------------
+
+unsigned long long FileLegacyAdapter::tell() {
+ return pj_ctx_ftell(m_ctx, m_fp);
+}
+
+// ---------------------------------------------------------------------------
+
+std::unique_ptr<File> FileLegacyAdapter::open(PJ_CONTEXT *ctx,
+ const char *filename) {
+ auto fid = pj_ctx_fopen(ctx, filename, "rb");
+ return std::unique_ptr<File>(fid ? new FileLegacyAdapter(ctx, fid)
+ : nullptr);
+}
+
+#endif // REMOVE_LEGACY_SUPPORT
+
+// ---------------------------------------------------------------------------
+
+std::unique_ptr<File> FileManager::open(PJ_CONTEXT *ctx, const char *filename) {
+#ifndef REMOVE_LEGACY_SUPPORT
+ // If the user has specified a legacy fileapi, use it
+ if (ctx->fileapi_legacy != pj_get_default_fileapi()) {
+ return FileLegacyAdapter::open(ctx, filename);
+ }
+#endif
+ return FileStdio::open(ctx, filename);
+}
+
+NS_PROJ_END
diff --git a/src/filemanager.hpp b/src/filemanager.hpp
new file mode 100644
index 00000000..19478c48
--- /dev/null
+++ b/src/filemanager.hpp
@@ -0,0 +1,68 @@
+/******************************************************************************
+ * Project: PROJ
+ * Purpose: File manager
+ * Author: Even Rouault, <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2019, Even Rouault, <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef FILEMANAGER_HPP_INCLUDED
+#define FILEMANAGER_HPP_INCLUDED
+
+#include <memory>
+
+#include "proj.h"
+#include "proj/util.hpp"
+
+NS_PROJ_START
+
+class File;
+
+class FileManager {
+ private:
+ FileManager() = delete;
+
+ public:
+ // "Low-level" interface.
+ static std::unique_ptr<File> open(PJ_CONTEXT *ctx, const char *filename);
+
+ // "High-level" interface, honoring PROJ_LIB and the like.
+ static std::unique_ptr<File> open_resource_file(PJ_CONTEXT *ctx,
+ const char *name);
+};
+
+// ---------------------------------------------------------------------------
+
+class File {
+ protected:
+ File();
+
+ public:
+ virtual ~File();
+ virtual size_t read(void *buffer, size_t sizeBytes) = 0;
+ virtual bool seek(unsigned long long offset, int whence = SEEK_SET) = 0;
+ virtual unsigned long long tell() = 0;
+};
+
+NS_PROJ_END
+
+#endif // FILEMANAGER_HPP_INCLUDED \ No newline at end of file
diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake
index d4c95092..eacc7a23 100644
--- a/src/lib_proj.cmake
+++ b/src/lib_proj.cmake
@@ -282,6 +282,8 @@ set(SRC_LIBPROJ_CORE
tracing.cpp
grids.hpp
grids.cpp
+ filemanager.hpp
+ filemanager.cpp
${CMAKE_CURRENT_BINARY_DIR}/proj_config.h
)
diff --git a/src/open_lib.cpp b/src/open_lib.cpp
index 24c31033..e1572754 100644
--- a/src/open_lib.cpp
+++ b/src/open_lib.cpp
@@ -44,6 +44,7 @@
#include "proj/internal/internal.hpp"
#include "proj_internal.h"
+#include "filemanager.hpp"
static const char * proj_lib_name =
#ifdef PROJ_LIB
@@ -197,16 +198,17 @@ static const char *get_path_from_win32_projlib(const char *name, std::string& ou
#endif
/************************************************************************/
-/* pj_open_lib_ex() */
+/* pj_open_lib_internal() */
/************************************************************************/
-static PAFile
-pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
- char* out_full_filename, size_t out_full_filename_size) {
+static void*
+pj_open_lib_internal(projCtx ctx, const char *name, const char *mode,
+ void* (*open_file)(projCtx, const char*, const char*),
+ char* out_full_filename, size_t out_full_filename_size) {
try {
std::string fname;
const char *sysname = nullptr;
- PAFile fid = nullptr;
+ void* fid = nullptr;
#ifdef WIN32
static const char dir_chars[] = "/\\";
const char dirSeparator = ';';
@@ -254,7 +256,7 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
fname += DIR_CHAR;
fname += name;
sysname = fname.c_str();
- fid = pj_ctx_fopen(ctx, sysname, mode);
+ fid = open_file(ctx, sysname, mode);
} catch( const std::exception& )
{
}
@@ -270,7 +272,7 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
fname += DIR_CHAR;
fname += name;
sysname = fname.c_str();
- fid = pj_ctx_fopen(ctx, sysname, mode);
+ fid = open_file(ctx, sysname, mode);
if( fid )
break;
}
@@ -290,7 +292,7 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
}
assert(sysname); // to make Coverity Scan happy
- if ( fid != nullptr || (fid = pj_ctx_fopen(ctx, sysname, mode)) != nullptr)
+ if ( fid != nullptr || (fid = open_file(ctx, sysname, mode)) != nullptr)
{
if( out_full_filename != nullptr && out_full_filename_size > 0 )
{
@@ -322,18 +324,54 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode,
}
/************************************************************************/
+/* pj_open_file_with_manager() */
+/************************************************************************/
+
+static void* pj_open_file_with_manager(projCtx ctx, const char *name,
+ const char * /* mode */)
+{
+ return NS_PROJ::FileManager::open(ctx, name).release();
+}
+
+/************************************************************************/
+/* FileManager::open_resource_file() */
+/************************************************************************/
+
+std::unique_ptr<NS_PROJ::File> NS_PROJ::FileManager::open_resource_file(
+ projCtx ctx, const char *name)
+{
+ return std::unique_ptr<NS_PROJ::File>(
+ reinterpret_cast<NS_PROJ::File*>(
+ pj_open_lib_internal(ctx, name, "rb",
+ pj_open_file_with_manager,
+ nullptr, 0)));
+}
+
+/************************************************************************/
/* pj_open_lib() */
/************************************************************************/
+#ifndef REMOVE_LEGACY_SUPPORT
+
+// Used by following legacy function
+static void* pj_ctx_fopen_adapter(projCtx ctx, const char *name, const char *mode)
+{
+ return pj_ctx_fopen(ctx, name, mode);
+}
+
+// Legacy function
PAFile
pj_open_lib(projCtx ctx, const char *name, const char *mode) {
- return pj_open_lib_ex(ctx, name, mode, nullptr, 0);
+ return (PAFile)pj_open_lib_internal(ctx, name, mode, pj_ctx_fopen_adapter, nullptr, 0);
}
+#endif // REMOVE_LEGACY_SUPPORT
+
/************************************************************************/
/* pj_find_file() */
/************************************************************************/
+
/** Returns the full filename corresponding to a proj resource file specified
* as a short filename.
*
@@ -348,11 +386,14 @@ pj_open_lib(projCtx ctx, const char *name, const char *mode) {
int pj_find_file(projCtx ctx, const char *short_filename,
char* out_full_filename, size_t out_full_filename_size)
{
- PAFile f = pj_open_lib_ex(ctx, short_filename, "rb", out_full_filename,
- out_full_filename_size);
+ auto f = reinterpret_cast<NS_PROJ::File*>(
+ pj_open_lib_internal(ctx, short_filename, "rb",
+ pj_open_file_with_manager,
+ out_full_filename,
+ out_full_filename_size));
if( f != nullptr )
{
- pj_ctx_fclose(ctx, f);
+ delete f;
return 1;
}
return 0;