WSL/SLF GitLab Repository

Config.cc 5.65 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/***********************************************************************************/
/*  Copyright 2009 WSL Institute for Snow and Avalanche Research    SLF-DAVOS      */
/***********************************************************************************/
/* This file is part of MeteoIO.
    MeteoIO is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    MeteoIO is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with MeteoIO.  If not, see <http://www.gnu.org/licenses/>.
*/
18
#include <meteoio/Config.h>
19
20
21
22
23

using namespace std;

namespace mio {

24
const std::string Config::defaultSection = "GENERAL";
25
26

//Constructors
27
Config::Config()
28
29
30
31
{
	//nothing is even put in the property map, the user will have to fill it by himself
}

32
Config::Config(const std::string& i_filename)
33
{
34
	addFile(i_filename);
35
36
}

37
38
39
40
41
42
43
44
45
ConfigProxy Config::get(const std::string& key, const Options& opt) const 
{
	return ConfigProxy(*this, key, Config::defaultSection, opt);
}

ConfigProxy Config::get(const std::string& key, const std::string& section, const Options& opt) const 
{
	return ConfigProxy(*this, key, section, opt);
}
46
47

//Populating the property map
48
void Config::addFile(const std::string& i_filename)
49
{
50
51
	sourcename = i_filename;
	parseFile(i_filename);
52
53
}

54
void Config::addCmdLine(const std::string& cmd_line)
55
56
57
58
59
{
	sourcename = std::string("Command line");
	parseCmdLine(cmd_line);
}

60
void Config::addKey(const std::string& key, const std::string& value)
61
{
62
	std::string section=defaultSection;
63
64
65
	addKey(key, section, value);
}

66
void Config::addKey(std::string key, std::string section, const std::string& value)
67
{
68
69
70
	IOUtils::toUpper(key);
	IOUtils::toUpper(section);
	properties[section + "::" + key] = value;
71
72
}

73
std::ostream& operator<<(std::ostream &os, const Config& cfg)
74
{
75
	os << "<Config>\n";
76
77
78
79
	map<string,string>::const_iterator it;
	for (it=cfg.properties.begin(); it != cfg.properties.end(); it++){
		os << (*it).first << " -> " << (*it).second << "\n";
	}
80
	os << "</Config>\n";
81
82
	return os;
}
83
84

//Parsing
85
void Config::parseCmdLine(const std::string& cmd_line)
86
87
88
89
90
{
	(void)cmd_line;
	throw IOException("Nothing implemented here", AT);
}

91
void Config::parseFile(const std::string& filename)
92
93
94
{
	std::ifstream fin; //Input file streams
	unsigned int linenr = 0;
95
	std::string line="", section=defaultSection;
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
	
	if (!IOUtils::validFileName(filename)) {
		throw InvalidFileNameException(filename,AT);
	}
  
	//Check whether file exists
	if (!IOUtils::fileExists(filename)) {
		throw FileNotFoundException(filename, AT);
	}
  
	//Open file
	fin.open (filename.c_str(), ifstream::in);
	if (fin.fail()) {
		throw FileAccessException(filename, AT);
	}

	char eoln = IOUtils::getEoln(fin); //get the end of line character for the file
	
	try {
		do {
			getline(fin, line, eoln); //read complete line
			parseLine(linenr++, line, section);
		} while(!fin.eof());
		fin.close();
	} catch(std::exception& e){
		if (fin.is_open()) {//close fin if open
			fin.close();
		}
		throw;
	}
}

128
void Config::parseLine(const unsigned int& linenr, std::string& line, std::string& section)
129
{
130
	//First thing cut away any possible comments (may start with "#" or ";")
131
	IOUtils::stripComments(line);
132

133
	IOUtils::trim(line);    //delete leading and trailing whitespace characters
134
135
136
	if (line.length() == 0) //ignore empty lines
		return;

137
	stringstream tmp;       //stringstream to convert the unsigned int linenr into a string
138
139
140
141
142
143
144
145
146
147
148
149
150
	if (line[0] == '['){
		size_t endpos = line.find_last_of(']');
		if ((endpos == string::npos) || (endpos < 2) || (endpos != (line.length()-1))){
			tmp << linenr;
			throw IOException("Section header corrupt in line " + tmp.str(), AT);
		} else {
			section = line.substr(1,endpos-1);
			IOUtils::toUpper(section);
			return;
		}
	}

	//At this point line can only be a key value pair
151
	if (!IOUtils::readKeyValuePair(line, "=", properties, section+"::", true)){
152
153
154
155
156
157
		tmp << linenr;
		throw InvalidFormatException("Error reading key value pair in " + sourcename + " line:" + tmp.str(), AT);    
	}
}

//Return key/value filename
158
std::string Config::getSourceName()
159
160
161
162
{
	return sourcename;
}

163
164
unsigned int Config::findKeys(std::vector<std::string>& vecResult, std::string keystart, 
						std::string section) const
165
166
167
{
	vecResult.clear();

168
169
170
171
172
173
	if (section.length() == 0) //enforce the default section if user tries to give empty section string
		section = defaultSection;

	IOUtils::toUpper(section);
	IOUtils::toUpper(keystart);
	string _keystart = section + "::" + keystart;
174
175
176
177
178

	//Loop through keys, look for substring match - push it into vecResult
	map<string,string>::const_iterator it;
	for (it=properties.begin(); it != properties.end(); it++){
		string tmp = (*it).first;
179
		tmp = tmp.substr(0, _keystart.length());
180
181
182
183
184

		int matchcount = _keystart.compare(tmp);

		if (matchcount == 0){ //perfect match
			string tmp2 = it->first;
185
			tmp2 = tmp2.substr(section.length() + 2);
186
187
188
189
190
191
192
193
194
195
196
197
			vecResult.push_back(tmp2);
		}
	}

	return vecResult.size();
}

} //end namespace

#ifdef _POPC_
#include "marshal_meteoio.h"
using namespace mio; //HACK for POPC
198
void Config::Serialize(POPBuffer &buf, bool pack)
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
{
	if (pack)
	{
		buf.Pack(&sourcename,1);
		marshal_map_str_str(buf, properties, 0, FLAG_MARSHAL, NULL);
	}
	else
	{
		buf.UnPack(&sourcename,1);
		marshal_map_str_str(buf, properties, 0, !FLAG_MARSHAL, NULL);
	}
}
#endif

//} //namespace //HACK for POPC