Config.cc revision 10447:a465576671d4
1#include "Config.h"
2
3#include <fstream>
4
5#include "Assert.h"
6
7namespace LibUtil
8{
9    Config::Config(const String& delimiter_, const String& comment_, const String& sentry_)
10        : mDelimiter(delimiter_), mComment(comment_), mSentry(sentry_)
11    {}
12
13    Config::Config(const Config& config_)
14        : StringMap(config_)
15    {
16        mDelimiter = config_.mDelimiter;
17        mComment = config_.mComment;
18        mSentry = config_.mSentry;
19    }
20
21    Config::~Config()
22    {}
23
24    Config* Config::clone() const
25    {
26        return new Config(*this);
27    }
28
29    void Config::readFile(const String& filename_)
30    {
31        std::ifstream fin(filename_.c_str());
32
33        ASSERT(fin, "File not found: " + filename_);
34        fin >> (*this);
35        return;
36    }
37
38    void Config::readString(const String& str_)
39    {
40        String newString = str_;
41        newString.substitute(";", "\n");
42        std::istringstream iss(newString, std::istringstream::in);
43
44        iss >> (*this);
45    }
46
47    std::ostream& operator<<(std::ostream& ost_, const Config& config_)
48    {
49        Config::ConstIterator it;
50        for(it = config_.begin(); it != config_.end(); it++)
51        {
52            ost_ << it->first << " " << config_.mDelimiter << " ";
53            ost_ << it->second << std::endl;
54        }
55        return ost_;
56    }
57
58    std::istream& operator>>(std::istream& ist_, Config& config_)
59    {
60        // Set a Config from ist_
61        // Read in keys and values, keeping internal whitespace
62        typedef String::size_type pos;
63        const String& delim  = config_.mDelimiter;  // separator
64        const String& comm   = config_.mComment;    // comment
65        const String& sentry = config_.mSentry;     // end of file sentry
66        const pos skip = delim.length();        // length of separator
67
68        String nextline = "";  // might need to read ahead to see where value ends
69
70        while(ist_ || nextline.length() > 0)
71        {
72            // Read an entire line at a time
73            String line;
74            if(nextline.length() > 0)
75            {
76                line = nextline;  // we read ahead; use it now
77                nextline = "";
78            }
79            else
80            {
81                //std::getline(ist_, line);
82                safeGetline(ist_, line);
83            }
84
85            // Ignore comments and the spaces on both ends
86            line = line.substr(0, line.find(comm));
87            line.trim();
88
89            // Check for end of file sentry
90            if((sentry != "") && (line.find(sentry) != String::npos)) return ist_;
91
92            if(line.length() == 0)
93                continue;
94
95            // Parse the line if it contains a delimiter
96            pos delimPos = line.find(delim);
97            ASSERT((delimPos < String::npos), "Invalid config line: '" + line + "'");
98
99            // Extract the key
100            String key = line.substr(0, delimPos);
101            line.replace(0, delimPos+skip, "");
102
103            // See if value continues on the next line
104            // Stop at blank line, next line with a key, end of stream,
105            // or end of file sentry
106            bool terminate = false;
107            while(!terminate && ist_)
108            {
109                if(line.at(line.size() - 1) == '\\')
110                    line.erase(line.size() - 1);
111                else
112                    break;
113
114                //std::getline(ist_, nextline);
115                safeGetline(ist_, nextline);
116                terminate = true;
117
118                String nlcopy = nextline;
119                nlcopy.trim();
120                if(nlcopy == "") continue;
121
122                nextline = nextline.substr(0, nextline.find(comm));
123                //if(nextline.find(delim) != String::npos)
124                //    continue;
125                if((sentry != "") && (nextline.find(sentry) != String::npos))
126                    continue;
127
128                //nlcopy = nextline;
129                //nlcopy.trim();
130                //if(nlcopy != "") line += "\n";
131                line += nextline;
132                nextline = "";
133                terminate = false;
134            }
135
136            // Store key and value
137            key.trim();
138            line.trim();
139            config_.set(key, line);  // overwrites if key is repeated
140        }
141        return ist_;
142    }
143}
144
145