aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/filemanager.cpp56
-rw-r--r--src/filemanager.hpp3
-rw-r--r--src/init.cpp48
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);