@@ -143,6 +143,8 @@ std::string File::read_line(size_t maxLen, bool &maxLenReached,
143143
144144// ---------------------------------------------------------------------------
145145
146+ #if !USE_ONLY_EMBEDDED_RESOURCE_FILES
147+
146148#ifdef _WIN32
147149
148150/* The bulk of utf8towc()/utf8fromwc() is derived from the utf.c module from
@@ -805,6 +807,8 @@ std::unique_ptr<File> FileStdio::open(PJ_CONTEXT *ctx, const char *filename,
805807
806808#endif // _WIN32
807809
810+ #endif // !USE_ONLY_EMBEDDED_RESOURCE_FILES
811+
808812// ---------------------------------------------------------------------------
809813
810814class FileApiAdapter : public File {
@@ -893,6 +897,80 @@ std::unique_ptr<File> FileApiAdapter::open(PJ_CONTEXT *ctx,
893897
894898// ---------------------------------------------------------------------------
895899
900+ #if EMBED_RESOURCE_FILES
901+
902+ class FileMemory : public File {
903+ PJ_CONTEXT *m_ctx;
904+ const unsigned char *const m_data;
905+ const size_t m_size;
906+ size_t m_pos = 0 ;
907+
908+ FileMemory (const FileMemory &) = delete ;
909+ FileMemory &operator =(const FileMemory &) = delete ;
910+
911+ protected:
912+ FileMemory (const std::string &filename, PJ_CONTEXT *ctx,
913+ const unsigned char *data, size_t size)
914+ : File(filename), m_ctx(ctx), m_data(data), m_size(size) {}
915+
916+ public:
917+ size_t read (void *buffer, size_t sizeBytes) override ;
918+ size_t write (const void *, size_t ) override ;
919+ bool seek (unsigned long long offset, int whence = SEEK_SET) override ;
920+ unsigned long long tell () override { return m_pos; }
921+ void reassign_context (PJ_CONTEXT *ctx) override { m_ctx = ctx; }
922+
923+ bool hasChanged () const override { return false ; }
924+
925+ static std::unique_ptr<File> open (PJ_CONTEXT *ctx, const char *filename,
926+ FileAccess access,
927+ const unsigned char *data, size_t size) {
928+ if (access != FileAccess::READ_ONLY)
929+ return nullptr ;
930+ return std::unique_ptr<File>(new FileMemory (filename, ctx, data, size));
931+ }
932+ };
933+
934+ size_t FileMemory::read (void *buffer, size_t sizeBytes) {
935+ if (m_pos >= m_size)
936+ return 0 ;
937+ if (sizeBytes >= m_size - m_pos) {
938+ const size_t bytesToCopy = m_size - m_pos;
939+ memcpy (buffer, m_data + m_pos, bytesToCopy);
940+ m_pos = m_size;
941+ return bytesToCopy;
942+ }
943+ memcpy (buffer, m_data + m_pos, sizeBytes);
944+ m_pos += sizeBytes;
945+ return sizeBytes;
946+ }
947+
948+ size_t FileMemory::write (const void *, size_t ) {
949+ // shouldn't happen given we have bailed out in open() in non read-only
950+ // modes
951+ return 0 ;
952+ }
953+
954+ bool FileMemory::seek (unsigned long long offset, int whence) {
955+ if (whence == SEEK_SET) {
956+ m_pos = static_cast <size_t >(offset);
957+ return m_pos == offset;
958+ } else if (whence == SEEK_CUR) {
959+ const unsigned long long newPos = m_pos + offset;
960+ m_pos = static_cast <size_t >(newPos);
961+ return m_pos == newPos;
962+ } else {
963+ if (offset != 0 )
964+ return false ;
965+ m_pos = m_size;
966+ return true ;
967+ }
968+ }
969+
970+ #endif
971+
972+ // ---------------------------------------------------------------------------
973+
896974std::unique_ptr<File> FileManager::open (PJ_CONTEXT *ctx, const char *filename,
897975 FileAccess access) {
898976 if (starts_with (filename, " http://" ) || starts_with (filename, " https://" )) {
@@ -909,11 +987,31 @@ std::unique_ptr<File> FileManager::open(PJ_CONTEXT *ctx, const char *filename,
909987 if (ctx->fileApi .open_cbk != nullptr ) {
910988 return FileApiAdapter::open (ctx, filename, access);
911989 }
990+
991+ std::unique_ptr<File> ret;
992+ #if !(EMBED_RESOURCE_FILES && USE_ONLY_EMBEDDED_RESOURCE_FILES)
912993#ifdef _WIN32
913- return FileWin32::open (ctx, filename, access);
994+ ret = FileWin32::open (ctx, filename, access);
914995#else
915- return FileStdio::open (ctx, filename, access);
996+ ret = FileStdio::open (ctx, filename, access);
916997#endif
998+ #endif
999+
1000+ #if EMBED_RESOURCE_FILES
1001+ #if USE_ONLY_EMBEDDED_RESOURCE_FILES
1002+ if (!ret)
1003+ #endif
1004+ {
1005+ unsigned int size = 0 ;
1006+ const unsigned char *in_memory_data =
1007+ pj_get_embedded_resource (filename, &size);
1008+ if (in_memory_data) {
1009+ ret = FileMemory::open (ctx, filename, access, in_memory_data, size);
1010+ }
1011+ }
1012+ #endif
1013+
1014+ return ret;
9171015}
9181016
9191017// ---------------------------------------------------------------------------
@@ -1574,6 +1672,24 @@ static void *pj_open_lib_internal(
15741672 errno = 0 ;
15751673 }
15761674
1675+ #if EMBED_RESOURCE_FILES
1676+ if (!fid && fname != name && name[0 ] != ' .' && name[0 ] != ' /' &&
1677+ name[0 ] != ' ~' && !starts_with (name, " http://" ) &&
1678+ !starts_with (name, " https://" )) {
1679+ fid = open_file (ctx, name, mode);
1680+ if (fid) {
1681+ if (out_full_filename != nullptr &&
1682+ out_full_filename_size > 0 ) {
1683+ // cppcheck-suppress nullPointer
1684+ strncpy (out_full_filename, name, out_full_filename_size);
1685+ out_full_filename[out_full_filename_size - 1 ] = ' \0 ' ;
1686+ }
1687+ fname = name;
1688+ errno = 0 ;
1689+ }
1690+ }
1691+ #endif
1692+
15771693 if (ctx->last_errno == 0 && errno != 0 )
15781694 proj_context_errno_set (ctx, errno);
15791695
@@ -1870,20 +1986,9 @@ void pj_load_ini(PJ_CONTEXT *ctx) {
18701986
18711987 ctx->iniFileLoaded = true ;
18721988 std::string content;
1873- std::unique_ptr<NS_PROJ::File> file;
1874- #ifndef USE_ONLY_EMBEDDED_RESOURCE_FILES
1875- file.reset (reinterpret_cast <NS_PROJ::File *>(pj_open_lib_internal (
1876- ctx, " proj.ini" , " rb" , pj_open_file_with_manager, nullptr , 0 )));
1877- #endif
1878- if (!file) {
1879- #ifdef EMBED_RESOURCE_FILES
1880- unsigned int content_size = 0 ;
1881- const char *c_content = pj_get_embedded_proj_ini (&content_size);
1882- content.assign (c_content, content_size);
1883- #else
1884- return ;
1885- #endif
1886- }
1989+ auto file = std::unique_ptr<NS_PROJ::File>(
1990+ reinterpret_cast <NS_PROJ::File *>(pj_open_lib_internal (
1991+ ctx, " proj.ini" , " rb" , pj_open_file_with_manager, nullptr , 0 )));
18871992 if (file) {
18881993 file->seek (0 , SEEK_END);
18891994 const auto filesize = file->tell ();
0 commit comments