diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/filemanager.cpp | 56 | ||||
| -rw-r--r-- | src/filemanager.hpp | 3 | ||||
| -rw-r--r-- | src/init.cpp | 48 |
3 files changed, 78 insertions, 29 deletions
diff --git a/src/filemanager.cpp b/src/filemanager.cpp index 4218fde1..75476974 100644 --- a/src/filemanager.cpp +++ b/src/filemanager.cpp @@ -70,6 +70,62 @@ File::File(const std::string &name) : name_(name) {} File::~File() = default; +// --------------------------------------------------------------------------- + +std::string File::read_line(size_t maxLen, bool &maxLenReached, + bool &eofReached) { + constexpr size_t MAX_MAXLEN = 1024 * 1024; + maxLen = std::min(maxLen, MAX_MAXLEN); + while (true) { + // Consume existing lines in buffer + size_t pos = readLineBuffer_.find_first_of("\r\n"); + if (pos != std::string::npos) { + if (pos > maxLen) { + std::string ret(readLineBuffer_.substr(0, maxLen)); + readLineBuffer_ = readLineBuffer_.substr(maxLen); + maxLenReached = true; + eofReached = false; + return ret; + } + std::string ret(readLineBuffer_.substr(0, pos)); + if (readLineBuffer_[pos] == '\r' && + readLineBuffer_[pos + 1] == '\n') { + pos += 1; + } + readLineBuffer_ = readLineBuffer_.substr(pos + 1); + maxLenReached = false; + eofReached = false; + return ret; + } + + const size_t prevSize = readLineBuffer_.size(); + if (maxLen <= prevSize) { + std::string ret(readLineBuffer_.substr(0, maxLen)); + readLineBuffer_ = readLineBuffer_.substr(maxLen); + maxLenReached = true; + eofReached = false; + return ret; + } + + if (eofReadLine_) { + std::string ret = readLineBuffer_; + readLineBuffer_.clear(); + maxLenReached = false; + eofReached = ret.empty(); + return ret; + } + + readLineBuffer_.resize(maxLen); + const size_t nRead = + read(&readLineBuffer_[prevSize], maxLen - prevSize); + if (nRead < maxLen - prevSize) + eofReadLine_ = true; + readLineBuffer_.resize(prevSize + nRead); + } +} + +// --------------------------------------------------------------------------- + #ifdef _WIN32 /* The bulk of utf8towc()/utf8fromwc() is derived from the utf.c module from diff --git a/src/filemanager.hpp b/src/filemanager.hpp index 554bd325..2761b83c 100644 --- a/src/filemanager.hpp +++ b/src/filemanager.hpp @@ -74,6 +74,8 @@ class FileManager { class File { protected: std::string name_; + std::string readLineBuffer_{}; + bool eofReadLine_ = false; explicit File(const std::string &name); public: @@ -84,6 +86,7 @@ class File { virtual unsigned long long tell() = 0; virtual void reassign_context(PJ_CONTEXT *ctx) = 0; virtual bool hasChanged() const = 0; + std::string read_line(size_t maxLen, bool &maxLenReached, bool &eofReached); const std::string &name() const { return name_; } }; diff --git a/src/init.cpp b/src/init.cpp index 19fcf47b..ba3d86e4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -39,6 +39,7 @@ #include "geodesic.h" #include "proj.h" #include "proj_internal.h" +#include "filemanager.hpp" #include <math.h> @@ -83,18 +84,10 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { char *fname, *section; const char *key; char *buffer = nullptr; - char *line = nullptr; - PAFile fid; size_t n; - - line = static_cast<char*>(pj_malloc (MAX_LINE_LENGTH + 1)); - if (nullptr==line) - return nullptr; - fname = static_cast<char*>(pj_malloc (MAX_PATH_FILENAME+ID_TAG_MAX+3)); if (nullptr==fname) { - pj_dealloc (line); return nullptr; } @@ -106,7 +99,6 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { key += 5; if (MAX_PATH_FILENAME + ID_TAG_MAX + 2 < strlen (key)) { pj_dealloc (fname); - pj_dealloc (line); return nullptr; } memmove (fname, key, strlen (key) + 1); @@ -116,7 +108,6 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { if (nullptr==section) { proj_context_errno_set (ctx, PJD_ERR_NO_COLON_IN_INIT_STRING); pj_dealloc (fname); - pj_dealloc (line); return nullptr; } *section = 0; @@ -126,36 +117,36 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { "get_init_string: searching for section [%s] in init file [%s]", section, fname); - fid = pj_open_lib (ctx, fname, "rt"); - if (nullptr==fid) { + auto file = NS_PROJ::FileManager::open_resource_file(ctx, fname); + if (nullptr==file) { pj_dealloc (fname); - pj_dealloc (line); proj_context_errno_set (ctx, PJD_ERR_NO_OPTION_IN_INIT_FILE); return nullptr; } /* Search for section in init file */ + std::string line; for (;;) { + bool eofReached = false; + bool maxLenReached = false; + line = file->read_line(MAX_LINE_LENGTH, maxLenReached, eofReached); /* End of file? */ - if (nullptr==pj_ctx_fgets (ctx, line, MAX_LINE_LENGTH, fid)) { - pj_dealloc (buffer); + if (maxLenReached || eofReached) { pj_dealloc (fname); - pj_dealloc (line); - pj_ctx_fclose (ctx, fid); proj_context_errno_set (ctx, PJD_ERR_NO_OPTION_IN_INIT_FILE); return nullptr; } /* At start of right section? */ - pj_chomp (line); + pj_chomp (&line[0]); if ('<'!=line[0]) continue; - if (strlen (line) < n + 2) + if (strlen (line.c_str()) < n + 2) continue; if (line[n + 1] != '>') continue; - if (0==strncmp (line + 1, section, n)) + if (0==strncmp (line.data() + 1, section, n)) break; } @@ -163,13 +154,11 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { buffer = static_cast<char*>(pj_malloc (current_buffer_size)); if (nullptr==buffer) { pj_dealloc (fname); - pj_dealloc (line); - pj_ctx_fclose (ctx, fid); return nullptr; } /* Skip the "<section>" indicator, and copy the rest of the line over */ - strcpy (buffer, line + strlen (section) + 2); + strcpy (buffer, line.data() + strlen (section) + 2); /* Copy the remaining lines of the section to buffer */ for (;;) { @@ -183,15 +172,18 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { break; } + bool eofReached = false; + bool maxLenReached = false; + line = file->read_line(MAX_LINE_LENGTH, maxLenReached, eofReached); /* End of file? - done! */ - if (nullptr==pj_ctx_fgets (ctx, line, MAX_LINE_LENGTH, fid)) + if (maxLenReached || eofReached) break; /* Otherwise, handle the line. It MAY be the start of the next section, */ /* but that will be handled at the start of next trip through the loop */ buffer_length = strlen (buffer); - pj_chomp (line); /* Remove '#' style comments */ - next_length = strlen (line) + buffer_length + 2; + pj_chomp (&line[0]); /* Remove '#' style comments */ + next_length = strlen (line.data()) + buffer_length + 2; if (next_length > current_buffer_size) { char *b = static_cast<char*>(pj_malloc (2 * current_buffer_size)); if (nullptr==b) { @@ -205,12 +197,10 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) { buffer = b; } buffer[buffer_length] = ' '; - strcpy (buffer + buffer_length + 1, line); + strcpy (buffer + buffer_length + 1, line.data()); } - pj_ctx_fclose (ctx, fid); pj_dealloc (fname); - pj_dealloc (line); if (nullptr==buffer) return nullptr; pj_shrink (buffer); |
