bpp-core  2.2.0
AttributesTools.cpp
Go to the documentation of this file.
1 //
2 // File: AttributesTools.cpp
3 // Created by: Julien Dutheil
4 // Created on: 2003
5 //
6 
7 /*
8  Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
9 
10  This software is a computer program whose purpose is to provide basal and
11  utilitary classes. This file belongs to the Bio++ Project.
12 
13  This software is governed by the CeCILL license under French law and
14  abiding by the rules of distribution of free software. You can use,
15  modify and/ or redistribute the software under the terms of the CeCILL
16  license as circulated by CEA, CNRS and INRIA at the following URL
17  "http://www.cecill.info".
18 
19  As a counterpart to the access to the source code and rights to copy,
20  modify and redistribute granted by the license, users are provided only
21  with a limited warranty and the software's author, the holder of the
22  economic rights, and the successive licensors have only limited
23  liability.
24 
25  In this respect, the user's attention is drawn to the risks associated
26  with loading, using, modifying and/or developing or reproducing the
27  software by the user in light of its specific status of free software,
28  that may mean that it is complicated to manipulate, and that also
29  therefore means that it is reserved for developers and experienced
30  professionals having in-depth computer knowledge. Users are therefore
31  encouraged to load and test the software's suitability as regards their
32  requirements in conditions enabling the security of their systems and/or
33  data to be ensured and, more generally, to use and operate it in the
34  same conditions as regards security.
35 
36  The fact that you are presently reading this means that you have had
37  knowledge of the CeCILL license and that you accept its terms.
38  */
39 
40 // From the STL:
41 #include <cstdlib>
42 #include <string>
43 #include <iostream>
44 #include <fstream>
45 #include <algorithm>
46 
47 using namespace std;
48 
49 #include "AttributesTools.h"
50 #include "../App/ApplicationTools.h"
51 #include "../Text/TextTools.h"
52 #include "../Io/FileTools.h"
53 
54 using namespace bpp;
55 
56 /******************************************************************************/
57 
58 std::vector<std::string> AttributesTools::getVector(int argc, char* argv[])
59 {
60  size_t n = static_cast<size_t>(argc);
61  vector<string> result(n);
62  for (size_t i = 1; i < n; ++i)
63  {
64  result[i] = string(argv[i]);
65  }
66  // Ignore first argc which is the program name!
67  return result;
68 }
69 
70 /******************************************************************************/
71 
72 std::map<std::string, std::string> AttributesTools::getAttributesMap(
73  const std::vector<std::string>& argv,
74  const std::string& delimiter)
75 {
76  map<string, string> am;
77  getAttributesMap(argv, am, delimiter);
78  return am;
79 }
80 
81 /******************************************************************************/
82 
83 void AttributesTools::getAttributesMap(
84  const std::vector<std::string>& argv,
85  std::map<std::string, std::string>& am,
86  const std::string& delimiter)
87 {
88  vector<string> argv2(argv.size());
89  // First make a few cleaning:
90  for (size_t i = 0; i < argv.size(); i++)
91  {
92  // Make a few corrections first:
93  string arg = removeComments(argv[i], string("#"), string("\n")); // remove shell comments.
94  arg = removeComments(arg, string("//"), string("\n")); // remove C simple comments.
95  arg = removeComments(arg, string("/*"), string("*/")); // remove C multiple comments.
96  arg = TextTools::removeWhiteSpaces(arg);
97  argv2[i] = arg;
98  }
99  // Now parse arguments:
100  for (size_t i = 0; i < argv.size(); i++)
101  {
102  string arg = argv2[i];
103  if (arg == "")
104  continue; // Skipping void line.
105  while (arg[arg.size() - 1] == '\\')
106  {
107  // Splitted line
108  i++;
109  arg = arg.substr(0, arg.length() - 1) + argv2[i];
110  }
111  // Parsing:
112  string::size_type limit = arg.find(delimiter, 0);
113  if (limit == string::npos)
114  {
115  // Invalid parameter
116  (*ApplicationTools::warning << "WARNING!!! Parameter '" << arg << "' has been ignored.").endLine();
117  }
118  else
119  {
120  string name = string(arg.begin(), arg.begin() + static_cast<ptrdiff_t>(limit));
121  string value = string(arg.begin() + static_cast<ptrdiff_t>(limit + delimiter.size()), arg.end());
122  // if ((name == "param") || (name == "params"))
123  // {
124  // //Recursive inclusion:
125  // getAttributesMapFromFile(value, am, delimiter);
126  // }
127  // else
128  am[name] = value;
129  }
130  }
131 }
132 
133 /******************************************************************************/
134 
135 void AttributesTools::getAttributesMapFromFile(
136  const std::string& file,
137  std::map<std::string, std::string>& params,
138  const std::string& delimiter)
139 {
140  cout << "Parsing file " << file << " for options." << endl;
141  ifstream input(file.c_str(), ios::in);
142  vector<string> lines = FileTools::putStreamIntoVectorOfStrings(input);
143  getAttributesMap(lines, params, delimiter);
144 }
145 
146 /******************************************************************************/
147 
148 std::map<std::string, std::string> AttributesTools::getAttributesMapFromFile(
149  const std::string& file,
150  const std::string& delimiter)
151 {
152  map<string, string> params;
153  getAttributesMapFromFile(file, params, delimiter);
154  return params;
155 }
156 
157 /******************************************************************************/
158 
159 void AttributesTools::actualizeAttributesMap(
160  std::map<std::string, std::string>& attMap,
161  const std::map<std::string, std::string>& atts)
162 {
163  for (map<string, string>::const_iterator i = atts.begin(); i != atts.end(); i++)
164  {
165  if ((i->first != "param") && (i->first != "params"))
166  attMap[i->first] = i->second;
167  }
168 }
169 
170 /******************************************************************************/
171 
172 void AttributesTools::resolveVariables(
173  std::map<std::string, std::string>& am,
174  char varCode,
175  char varBeg,
176  char varEnd)
177 throw (Exception)
178 {
179  // Now resolve any variable:
180  for (map<string, string>::iterator it = am.begin(); it != am.end(); it++)
181  {
182  string value = it->second;
183  string::size_type index1 = value.find(TextTools::toString(varCode) + TextTools::toString(varBeg));
184  while (index1 != string::npos)
185  {
186  string::size_type index2 = value.find(TextTools::toString(varEnd), index1);
187  if (index2 != string::npos)
188  {
189  string varName = value.substr(index1 + 2, index2 - index1 - 2);
190  map<string, string>::iterator varIt = am.find(varName);
191  string varValue = "";
192  if (varIt == am.end())
193  {
194  if (ApplicationTools::error)
195  (*ApplicationTools::error << "Variable '" << varName << "' is undefined and was ignored.").endLine();
196  }
197  else
198  {
199  varValue = varIt->second;
200  }
201  // Modify original field:
202  string newValue = value.substr(0, index1) + varValue + value.substr(index2 + 1);
203  it->second = newValue;
204  }
205  else
206  throw Exception("Syntax error, variable name is not closed.");
207  value = it->second;
208  index1 = value.find(TextTools::toString(varCode) + TextTools::toString(varBeg));
209  }
210  }
211 }
212 
213 /******************************************************************************/
214 
215 std::string AttributesTools::removeComments(
216  const std::string& s,
217  const std::string& begin,
218  const std::string& end)
219 {
220  string r = s;
221  string::size_type last = 0;
222  do
223  {
224  string::size_type first = r.find(begin, last);
225  if (first == string::npos)
226  return r; // No shell comment.
227  // else:
228  last = r.find(end, first);
229  if (last == string::npos)
230  {
231  r.erase(r.begin() + static_cast<ptrdiff_t>(first), r.end());
232  }
233  else
234  {
235  r.erase(r.begin() + static_cast<ptrdiff_t>(first), r.begin() + static_cast<ptrdiff_t>(last));
236  }
237  }
238  while (last != string::npos);
239  return r;
240 }
241 
242 /******************************************************************************/
243 
244 std::map<std::string, std::string> AttributesTools::parseOptions(int args, char** argv) throw (Exception)
245 {
246  // Get the parameters from command line:
247  map<string, string> cmdParams = AttributesTools::getAttributesMap(
248  AttributesTools::getVector(args, argv), "=");
249 
250  // Look for a specified file with parameters:
251  map<string, string> params;
252  std::map<std::string, std::string>::iterator it;
253 
254  if (cmdParams.find("param") != cmdParams.end())
255  {
256  string file = cmdParams["param"];
257  if (!FileTools::fileExists(file))
258  {
259  throw Exception("AttributesTools::parseOptions(). Parameter file not found.");
260  }
261  else
262  {
263  params = getAttributesMapFromFile(file, "=");
264  // Actualize attributes with ones passed to command line:
265  actualizeAttributesMap(params, cmdParams);
266  }
267  }
268  else
269  {
270  params = cmdParams;
271  }
272  // Resolve variables:
273  resolveVariables(params);
274 
275  std::vector<string> mapfile;
276  std::vector<string>::iterator imapfile;
277  string file;
278 
279  while (true)
280  {
281  it = params.find("param");
282  if (it != params.end())
283  {
284  file = it->second;
285  if (std::find(mapfile.begin(), mapfile.end(), file) == mapfile.end())
286  {
287  params.erase(it);
288  mapfile.push_back(file);
289  getAttributesMapFromFile(file, params, "=");
290  resolveVariables(params);
291  continue;
292  }
293  else
294  throw Exception("parsing error : Already used file " + file);
295  }
296  it = params.find("params");
297  if (it != params.end())
298  {
299  file = it->second;
300  if (find(mapfile.begin(), mapfile.end(), file) == mapfile.end())
301  {
302  params.erase(it);
303  mapfile.push_back(file);
304  getAttributesMapFromFile(file, params, "=");
305  resolveVariables(params);
306  continue;
307  }
308  else
309  throw Exception("parsing error : Already used file " + file);
310  }
311  break;
312  }
313 
314  return params;
315 }
316 
317 /******************************************************************************/
This class allows to perform a correspondence analysis.
STL namespace.
Exception base class.
Definition: Exceptions.h:57