--- a/src/conftree.cxx
+++ b/src/conftree.cxx
@@ -18,19 +18,19 @@
#include "conftree.hxx"
-#include <fnmatch.h> // for fnmatch
-#include <stdlib.h> // for abort
-#include <sys/stat.h> // for stat, st_mtime
-#include <unistd.h> // for access
-
-#include <algorithm> // for find
-#include <cstring> // for strlen
-#include <fstream> // for ifstream, ofstream
-#include <iostream> // for cerr, cout
-#include <sstream> // for stringstream
-#include <utility> // for pair
-
-#include "upmpdutils.hxx" // for trimstring, path_catslash, etc
+#include <fnmatch.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <utility>
+
+#include "upmpdutils.hxx"
using namespace std;
@@ -41,24 +41,19 @@
#define LOGDEB(X)
#endif
-#ifndef MIN
-#define MIN(A,B) ((A) < (B) ? (A) : (B))
-#endif
-
-#define LL 2048
-
void ConfSimple::parseinput(istream& input)
{
string submapkey;
- char cline[LL];
+ string cline;
bool appending = false;
string line;
bool eof = false;
for (;;) {
- cline[0] = 0;
- input.getline(cline, LL - 1);
- LOGDEB((stderr, "Parse:line: [%s] status %d\n", cline, int(status)));
+ cline.clear();
+ std::getline(input, cline);
+ LOGDEB((stderr, "Parse:line: [%s] status %d\n",
+ cline.c_str(), int(status)));
if (!input.good()) {
if (input.bad()) {
LOGDEB((stderr, "Parse: input.bad()\n"));
@@ -73,10 +68,11 @@
}
{
- int ll = strlen(cline);
- while (ll > 0 && (cline[ll - 1] == '\n' || cline[ll - 1] == '\r')) {
- cline[ll - 1] = 0;
- ll--;
+ string::size_type pos = cline.find_last_not_of("\n\r");
+ if (pos == string::npos) {
+ cline.clear();
+ } else if (pos != cline.length() - 1) {
+ cline.erase(pos + 1);
}
}
@@ -181,7 +177,7 @@
// It seems that there is no separate 'create if not exists'
// open flag. Have to truncate to create, but dont want to do
// this to an existing file !
- if (access(fname, 0) < 0) {
+ if (!path_exists(fname)) {
mode |= ios::trunc;
}
input.open(fname, mode);
@@ -268,29 +264,45 @@
}
// Appropriately output a subkey (nm=="") or variable line.
-// Splits long lines
+// We can't make any assumption about the data except that it does not
+// contain line breaks.
+// Avoid long lines if possible (for hand-editing)
+// We used to break at arbitrary places, but this was ennoying for
+// files with pure UTF-8 encoding (some files can be binary anyway),
+// because it made later editing difficult, as the file would no
+// longer have a valid encoding.
+// Any ASCII byte would be a safe break point for utf-8, but could
+// break some other encoding with, e.g. escape sequences? So break at
+// whitespace (is this safe with all encodings?).
+// Note that the choice of break point does not affect the validity of
+// the file data (when read back by conftree), only its ease of
+// editing with a normal editor.
static ConfSimple::WalkerCode varprinter(void *f, const string& nm,
const string& value)
{
- ostream *output = (ostream *)f;
+ ostream& output = *((ostream *)f);
if (nm.empty()) {
- *output << "\n[" << value << "]\n";
+ output << "\n[" << value << "]\n";
} else {
- string value1;
- if (value.length() < 60) {
- value1 = value;
+ output << nm << " = ";
+ if (nm.length() + value.length() < 75) {
+ output << value;
} else {
- string::size_type pos = 0;
- while (pos < value.length()) {
- string::size_type len = MIN(60, value.length() - pos);
- value1 += value.substr(pos, len);
- pos += len;
- if (pos < value.length()) {
- value1 += "\\\n";
+ string::size_type ll = 0;
+ for (string::size_type pos = 0; pos < value.length(); pos++) {
+ string::value_type c = value[pos];
+ output << c;
+ ll++;
+ // Break at whitespace if line too long and "a lot" of
+ // remaining data
+ if (ll > 50 && (value.length() - pos) > 10 &&
+ (c == ' ' || c == '\t')) {
+ ll = 0;
+ output << "\\\n";
}
}
}
- *output << nm << " = " << value1 << "\n";
+ output << "\n";
}
return ConfSimple::WALK_CONTINUE;
}
@@ -612,8 +624,9 @@
int ConfTree::get(const std::string& name, string& value, const string& sk)
const
{
- if (sk.empty() || sk[0] != '/') {
- // LOGDEB((stderr, "ConfTree::get: looking in global space\n"));
+ if (sk.empty() || !path_isabsolute(sk)) {
+ // LOGDEB((stderr, "ConfTree::get: looking in global space for [%s]\n",
+ // sk.c_str()));
return ConfSimple::get(name, value, sk);
}
@@ -635,7 +648,12 @@
if (pos != string::npos) {
msk.replace(pos, string::npos, string());
} else {
- break;
+#ifdef _WIN32
+ if (msk.size() == 2 && isalpha(msk[0]) && msk[1] == ':') {
+ msk.clear();
+ } else
+#endif
+ break;
}
}
return 0;