Switch to unified view

a/src/conftree.cxx b/src/conftree.cxx
...
...
16
 */
16
 */
17
#ifndef TEST_CONFTREE
17
#ifndef TEST_CONFTREE
18
18
19
#include "conftree.hxx"
19
#include "conftree.hxx"
20
20
21
#include <fnmatch.h>                    // for fnmatch
21
#include <fnmatch.h>
22
#include <stdlib.h>                     // for abort
22
#include <stdlib.h>
23
#include <sys/stat.h>                   // for stat, st_mtime
23
#include <sys/stat.h>
24
#include <unistd.h>                     // for access
24
#include <unistd.h>
25
25
26
#include <algorithm>                    // for find
26
#include <algorithm>
27
#include <cstring>                      // for strlen
27
#include <cstring>
28
#include <fstream>                      // for ifstream, ofstream
28
#include <fstream>
29
#include <iostream>                     // for cerr, cout
29
#include <iostream>
30
#include <sstream>                      // for stringstream
30
#include <sstream>
31
#include <utility>                      // for pair
31
#include <utility>
32
32
33
#include "upmpdutils.hxx"               // for trimstring, path_catslash, etc
33
#include "upmpdutils.hxx"
34
34
35
using namespace std;
35
using namespace std;
36
36
37
#undef DEBUG
37
#undef DEBUG
38
#ifdef DEBUG
38
#ifdef DEBUG
39
#define LOGDEB(X) fprintf X
39
#define LOGDEB(X) fprintf X
40
#else
40
#else
41
#define LOGDEB(X)
41
#define LOGDEB(X)
42
#endif
42
#endif
43
43
44
#ifndef MIN
45
#define MIN(A,B) ((A) < (B) ? (A) : (B))
46
#endif
47
48
#define LL 2048
49
50
void ConfSimple::parseinput(istream& input)
44
void ConfSimple::parseinput(istream& input)
51
{
45
{
52
    string submapkey;
46
    string submapkey;
53
    char cline[LL];
47
    string cline;
54
    bool appending = false;
48
    bool appending = false;
55
    string line;
49
    string line;
56
    bool eof = false;
50
    bool eof = false;
57
51
58
    for (;;) {
52
    for (;;) {
59
        cline[0] = 0;
53
        cline.clear();
60
        input.getline(cline, LL - 1);
54
        std::getline(input, cline);
61
        LOGDEB((stderr, "Parse:line: [%s] status %d\n", cline, int(status)));
55
        LOGDEB((stderr, "Parse:line: [%s] status %d\n",
56
                cline.c_str(), int(status)));
62
        if (!input.good()) {
57
        if (!input.good()) {
63
            if (input.bad()) {
58
            if (input.bad()) {
64
                LOGDEB((stderr, "Parse: input.bad()\n"));
59
                LOGDEB((stderr, "Parse: input.bad()\n"));
65
                status = STATUS_ERROR;
60
                status = STATUS_ERROR;
66
                return;
61
                return;
...
...
71
            // eof ends with a backslash, or there is no final \n
66
            // eof ends with a backslash, or there is no final \n
72
            eof = true;
67
            eof = true;
73
        }
68
        }
74
69
75
        {
70
        {
76
            int ll = strlen(cline);
71
            string::size_type pos = cline.find_last_not_of("\n\r");
77
            while (ll > 0 && (cline[ll - 1] == '\n' || cline[ll - 1] == '\r')) {
72
            if (pos == string::npos) {
78
                cline[ll - 1] = 0;
79
                ll--;
73
                cline.clear();
74
            } else if (pos != cline.length() - 1) {
75
                cline.erase(pos + 1);
80
            }
76
            }
81
        }
77
        }
82
78
83
        if (appending) {
79
        if (appending) {
84
            line += cline;
80
            line += cline;
...
...
179
    } else {
175
    } else {
180
        ios::openmode mode = ios::in | ios::out;
176
        ios::openmode mode = ios::in | ios::out;
181
        // It seems that there is no separate 'create if not exists'
177
        // It seems that there is no separate 'create if not exists'
182
        // open flag. Have to truncate to create, but dont want to do
178
        // open flag. Have to truncate to create, but dont want to do
183
        // this to an existing file !
179
        // this to an existing file !
184
        if (access(fname, 0) < 0) {
180
        if (!path_exists(fname)) {
185
            mode |= ios::trunc;
181
            mode |= ios::trunc;
186
        }
182
        }
187
        input.open(fname, mode);
183
        input.open(fname, mode);
188
        if (input.is_open()) {
184
        if (input.is_open()) {
189
            status = STATUS_RW;
185
            status = STATUS_RW;
...
...
266
    value = s->second;
262
    value = s->second;
267
    return 1;
263
    return 1;
268
}
264
}
269
265
270
// Appropriately output a subkey (nm=="") or variable line.
266
// Appropriately output a subkey (nm=="") or variable line.
271
// Splits long lines
267
// We can't make any assumption about the data except that it does not
268
// contain line breaks.
269
// Avoid long lines if possible (for hand-editing)
270
// We used to break at arbitrary places, but this was ennoying for
271
// files with pure UTF-8 encoding (some files can be binary anyway),
272
// because it made later editing difficult, as the file would no
273
// longer have a valid encoding.
274
// Any ASCII byte would be a safe break point for utf-8, but could
275
// break some other encoding with, e.g. escape sequences? So break at
276
// whitespace (is this safe with all encodings?).
277
// Note that the choice of break point does not affect the validity of
278
// the file data (when read back by conftree), only its ease of
279
// editing with a normal editor.
272
static ConfSimple::WalkerCode varprinter(void *f, const string& nm,
280
static ConfSimple::WalkerCode varprinter(void *f, const string& nm,
273
        const string& value)
281
        const string& value)
274
{
282
{
275
    ostream *output = (ostream *)f;
283
    ostream& output = *((ostream *)f);
276
    if (nm.empty()) {
284
    if (nm.empty()) {
277
        *output << "\n[" << value << "]\n";
285
        output << "\n[" << value << "]\n";
278
    } else {
286
    } else {
279
        string value1;
287
        output << nm << " = ";
280
        if (value.length() < 60) {
288
        if (nm.length() + value.length() < 75) {
281
            value1 = value;
289
            output << value;
282
        } else {
290
        } else {
283
            string::size_type pos = 0;
291
            string::size_type ll = 0;
284
            while (pos < value.length()) {
285
                string::size_type len = MIN(60, value.length() - pos);
292
            for (string::size_type pos = 0; pos < value.length(); pos++) {
286
                value1 += value.substr(pos, len);
293
                string::value_type c = value[pos];
294
                output << c;
287
                pos += len;
295
                ll++;
288
                if (pos < value.length()) {
296
                // Break at whitespace if line too long and "a lot" of
297
                // remaining data
298
                if (ll > 50 && (value.length() - pos) > 10 &&
299
                        (c == ' ' || c == '\t')) {
300
                    ll = 0;
289
                    value1 += "\\\n";
301
                    output << "\\\n";
290
                }
302
                }
291
            }
303
            }
292
        }
304
        }
293
        *output << nm << " = " << value1 << "\n";
305
        output << "\n";
294
    }
306
    }
295
    return ConfSimple::WALK_CONTINUE;
307
    return ConfSimple::WALK_CONTINUE;
296
}
308
}
297
309
298
// Set variable and rewrite data
310
// Set variable and rewrite data
...
...
610
// //////////////////////////////////////////////////////////////////////////
622
// //////////////////////////////////////////////////////////////////////////
611
623
612
int ConfTree::get(const std::string& name, string& value, const string& sk)
624
int ConfTree::get(const std::string& name, string& value, const string& sk)
613
const
625
const
614
{
626
{
615
    if (sk.empty() || sk[0] != '/') {
627
    if (sk.empty() || !path_isabsolute(sk)) {
616
        //  LOGDEB((stderr, "ConfTree::get: looking in global space\n"));
628
        // LOGDEB((stderr, "ConfTree::get: looking in global space for [%s]\n",
629
        // sk.c_str()));
617
        return ConfSimple::get(name, value, sk);
630
        return ConfSimple::get(name, value, sk);
618
    }
631
    }
619
632
620
    // Get writable copy of subkey path
633
    // Get writable copy of subkey path
621
    string msk = sk;
634
    string msk = sk;
...
...
633
        }
646
        }
634
        string::size_type pos = msk.rfind("/");
647
        string::size_type pos = msk.rfind("/");
635
        if (pos != string::npos) {
648
        if (pos != string::npos) {
636
            msk.replace(pos, string::npos, string());
649
            msk.replace(pos, string::npos, string());
637
        } else {
650
        } else {
651
#ifdef _WIN32
652
            if (msk.size() == 2 && isalpha(msk[0]) && msk[1] == ':') {
653
                msk.clear();
654
            } else
655
#endif
638
            break;
656
                break;
639
        }
657
        }
640
    }
658
    }
641
    return 0;
659
    return 0;
642
}
660
}
643
661