source: src/Parser/FormatParserStorage.cpp@ 70caa3

AutomationFragmentation_failures Candidate_v1.6.1 ChemicalSpaceEvaluator Exclude_Hydrogens_annealWithBondGraph ForceAnnealing_with_BondGraph_contraction-expansion StoppableMakroAction
Last change on this file since 70caa3 was 70caa3, checked in by Frederik Heber <frederik.heber@…>, 7 years ago

FIX: FormatParserStorage would open new streams per SaveAll().

  • we did not check whether an open stream was still present and always opened a new one: OutputAction would cause an "too many open files" at some point because all those streams (on the same filename) were never closed.
  • Property mode set to 100644
File size: 12.5 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/** \file FormatParserStorage.cpp
24 *
25 * date: Jun, 22 2010
26 * author: heber
27 *
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35//#include "CodePatterns/MemDebug.hpp"
36
37#include <iostream>
38#include <fstream>
39
40#include <boost/preprocessor/iteration/local.hpp>
41
42#include "CodePatterns/Assert.hpp"
43#include "CodePatterns/Log.hpp"
44
45#include "molecule.hpp"
46#include "FormatParserStorage.hpp"
47#include "ParserTypes.hpp"
48
49#include "MpqcParser.hpp"
50#include "PcpParser.hpp"
51#include "PdbParser.hpp"
52#include "Psi3Parser.hpp"
53#include "TremoloParser.hpp"
54#include "XmlParser.hpp"
55#include "XyzParser.hpp"
56
57#include "CodePatterns/Singleton_impl.hpp"
58
59const std::string FormatParserStorage::unknownTypeString("unknown");
60
61/** Constructor of class FormatParserStorage.
62 */
63FormatParserStorage::FormatParserStorage()
64{
65 ParserList.resize(ParserTypes_end, NULL);
66 ParserStream.resize(ParserTypes_end, NULL);
67 ParserPresent.resize(ParserTypes_end, false);
68 ParserDesiredOutputFormat.resize(ParserTypes_end, false);
69
70#include "ParserTypes.def"
71
72#define insert_print(z,n,seq,map, before, after) \
73 map .insert( std::make_pair( \
74 BOOST_PP_SEQ_ELEM(n, seq) \
75 , before < \
76 BOOST_PP_SEQ_ELEM(n, seq) \
77 > after \
78 ) );
79
80#define insert_invert_print(z,n,seq,map, before, after) \
81 map .insert( std::make_pair( before < \
82 BOOST_PP_SEQ_ELEM(n, seq) \
83 > after, \
84 BOOST_PP_SEQ_ELEM(n, seq) \
85 ) );
86
87 // fill ParserNames
88#if defined ParserTypes_END // do we have parameters at all?
89#define BOOST_PP_LOCAL_MACRO(n) insert_print(~, n, PARSERSEQUENCE, ParserNames, FormatParserTrait, ::name)
90#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
91#include BOOST_PP_LOCAL_ITERATE()
92#endif
93
94 // fill ParserLookupNames
95#if defined ParserTypes_END // do we have parameters at all?
96#define BOOST_PP_LOCAL_MACRO(n) insert_invert_print(~, n, PARSERSEQUENCE, ParserLookupNames, FormatParserTrait, ::name)
97#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
98#include BOOST_PP_LOCAL_ITERATE()
99#endif
100
101 // fill ParserSuffixes
102#if defined ParserTypes_END // do we have parameters at all?
103#define BOOST_PP_LOCAL_MACRO(n) insert_print(~, n, PARSERSEQUENCE, ParserSuffixes, FormatParserTrait, ::suffix)
104#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
105#include BOOST_PP_LOCAL_ITERATE()
106#endif
107
108 // fill ParserLookupSuffixes
109#if defined ParserTypes_END // do we have parameters at all?
110#define BOOST_PP_LOCAL_MACRO(n) insert_invert_print(~, n, PARSERSEQUENCE, ParserLookupSuffixes, FormatParserTrait, ::suffix)
111#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
112#include BOOST_PP_LOCAL_ITERATE()
113#endif
114
115 // fill ParserAddFunction
116#if defined ParserTypes_END // do we have parameters at all?
117#define BOOST_PP_LOCAL_MACRO(n) insert_print(~, n, PARSERSEQUENCE, ParserAddFunction, &FormatParserStorage::addParser, )
118#define BOOST_PP_LOCAL_LIMITS (0, ParserTypes_END-1)
119#include BOOST_PP_LOCAL_ITERATE()
120#endif
121
122#undef insert_print
123#undef insert_invert_print
124#include "ParserTypes.undef"
125
126 //std::cout << "ParserNames:" << std::endl << ParserNames << std::endl;
127 //std::cout << "ParserSuffixes:" << std::endl << ParserSuffixes << std::endl;
128 //std::cout << "ParserLookupNames:" << std::endl << ParserLookupNames << std::endl;
129 //std::cout << "ParserLookupSuffixes:" << std::endl << ParserLookupSuffixes << std::endl;
130 //std::cout << "ParserAddFunction:" << std::endl << ParserAddFunction << std::endl;
131
132}
133
134/** Destructor of class FormatParserStorage.
135 * Free all stored FormatParsers.
136 * Save on Exit.
137 */
138FormatParserStorage::~FormatParserStorage()
139{
140 for (ParserTypes iter = ParserTypes_begin; iter < ParserTypes_end; ++iter)
141 if (ParserPresent[iter]) {
142 // this will also flush the ParserStream
143 delete ParserList[iter];
144 // then we remove the stream itself
145 if (ParserStream[iter] != NULL) {
146 if (ParserStream[iter]->is_open())
147 ParserStream[iter]->close();
148 delete ParserStream[iter];
149 }
150 }
151}
152
153
154/** Tests whether a file and parsers are selected for saving.
155 */
156bool FormatParserStorage::isAbleToSave()
157{
158 if (prefix.empty())
159 return false;
160
161 for (ParserTypes iter = ParserTypes_begin; iter < ParserTypes_end; ++iter)
162 if (ParserPresent[iter] && ParserDesiredOutputFormat[iter])
163 return true;
164 return false;
165}
166
167/** Sets the filename of all current parsers in storage to prefix.suffix.
168 * \param &prefix prefix to use.
169 */
170void FormatParserStorage::SetOutputPrefixForAll(std::string &_prefix)
171{
172 prefix=_prefix;
173};
174
175/** Sets \a type as a format to be stored on call of SaveAll.
176 *
177 * @param type type to add to desired output formats
178 */
179void FormatParserStorage::setOutputFormat(ParserTypes type)
180{
181 LOG(0, "STATUS: Adding " << ParserNames[type] << " type to output.");
182 ParserDesiredOutputFormat[type] = true;
183}
184
185/** Sets \a type as a format to be stored on call of SaveAll.
186 *
187 * @param type type to add to desired output formats
188 */
189void FormatParserStorage::setOutputFormat(std::string type)
190{
191 std::map<std::string, ParserTypes>::const_iterator iter = ParserLookupNames.find(type);
192 ASSERT(iter != ParserLookupNames.end(),
193 "FormatParserStorage::setOutputFormat() - output format "+type+" is unknown.");
194 setOutputFormat(iter->second);
195}
196
197/** Saves the world in the desired output formats.
198 *
199 */
200void FormatParserStorage::SaveAll()
201{
202 std::string filename;
203 for (ParserTypes iter = ParserTypes_begin; iter < ParserTypes_end; ++iter) {
204 // open a new stream, if parser is desired. Reopen such stream if already present
205 if (ParserPresent[iter] && ParserDesiredOutputFormat[iter]) {
206 if (ParserStream[iter] != NULL) {
207 if (ParserStream[iter]->is_open()) {
208 ParserStream[iter]->flush();
209 ParserStream[iter]->close();
210 }
211 delete ParserStream[iter];
212 ParserStream[iter] = NULL;
213 ParserList[iter]->setOstream(ParserStream[iter]);
214 }
215 filename = prefix;
216 filename += ".";
217 filename += ParserSuffixes[iter];
218 ParserStream[iter] = new std::ofstream(filename.c_str());
219 ParserList[iter]->setOstream((std::ostream *)ParserStream[iter]);
220 }
221 }
222}
223
224
225ParserTypes FormatParserStorage::getTypeFromName(std::string type)
226{
227 if (ParserLookupNames.find(type) == ParserLookupNames.end()) {
228 ELOG(1, "Unknown type " << type << ".");
229 return ParserTypes_end;
230 } else
231 return ParserLookupNames[type];
232}
233
234ParserTypes FormatParserStorage::getTypeFromSuffix(std::string type)
235{
236 if (ParserLookupSuffixes.find(type) == ParserLookupSuffixes.end()) {
237 ELOG(1, "Unknown type " << type << ".");
238 return ParserTypes_end;
239 } else
240 return ParserLookupSuffixes[type];
241}
242
243const std::string &FormatParserStorage::getNameFromType(ParserTypes type)
244{
245 if (ParserNames.find(type) == ParserNames.end()) {
246 ELOG(1, "Unknown type " << type << ".");
247 return unknownTypeString;
248 } else
249 return ParserNames[type];
250}
251
252const std::string &FormatParserStorage::getSuffixFromType(ParserTypes type)
253{
254 if (ParserSuffixes.find(type) == ParserSuffixes.end()) {
255 ELOG(1, "Unknown type " << type << ".");
256 return unknownTypeString;
257 } else
258 return ParserSuffixes[type];
259}
260
261bool FormatParserStorage::add(ParserTypes ptype)
262{
263 if (ptype != ParserTypes_end) {
264 if (ParserAddFunction.find(ptype) != ParserAddFunction.end()) {
265 (getInstance().*(ParserAddFunction[ptype]))(); // we still need an object to work on ...
266 return true;
267 } else {
268 ELOG(1, "No parser to add for this known type " << ParserNames[ptype] << ", not implemented?");
269 return false;
270 }
271 } else {
272 return false;
273 }
274}
275
276bool FormatParserStorage::add(std::string type)
277{
278 enum ParserTypes Ptype = getTypeFromName(type);
279 return add(Ptype);
280}
281
282/** Recognizes type of file and parse via FormatParserStorage::load().
283 * \param filename path and filename
284 * \return true - parsing ok, false - suffix unknown
285 */
286bool FormatParserStorage::load(boost::filesystem::path filename)
287{
288 return load(filename.string());
289}
290
291/** Recognizes type of file and parse via FormatParserStorage::load().
292 * \param filename path and filename
293 * \return true - parsing ok, false - suffix unknown
294 */
295bool FormatParserStorage::load(std::string &filename)
296{
297 std::string FilenameSuffix = filename.substr(filename.find_last_of('.')+1, filename.length());
298 ifstream input;
299 LOG(0, "STATUS: Loading filler molecule " << filename
300 << " of suffix " << FilenameSuffix << ".");
301 input.open(filename.c_str());
302 const bool status = load(input, FilenameSuffix);
303 input.close();
304
305 return status;
306}
307
308/** Parses an istream depending on its suffix
309 * \param &input input stream
310 * \param suffix
311 * \return true - parsing ok, false - suffix unknown
312 */
313bool FormatParserStorage::load(std::istream &input, std::string &suffix)
314{
315 enum ParserTypes type = getTypeFromSuffix(suffix);
316 if (type != ParserTypes_end)
317 get(type).load(&input);
318 else
319 return false;
320 return true;
321}
322
323/** Stores all selected atoms in an ostream depending on its suffix
324 * \param &output output stream
325 * \param suffix
326 * \return true - storing ok, false - suffix unknown
327 */
328bool FormatParserStorage::saveSelectedAtoms(std::ostream &output, std::string suffix)
329{
330 const std::vector<const atom *> atoms =
331 const_cast<const World &>(World::getInstance()).getSelectedAtoms();
332 return save(output, suffix, atoms);
333}
334
335/** Stores all selected atoms in an ostream depending on its suffix
336 * We store in the order of the atomic ids, not in the order they appear in the molecules.
337 * Hence, we first create a vector from all selected molecules' atoms.
338 *
339 * TODO: Change here atom * to const atom * when FormatParserStorage::save() uses vector<const atom *>
340 *
341 * \param &output output stream
342 * \param suffix
343 * \return true - storing ok, false - suffix unknown
344 */
345bool FormatParserStorage::saveSelectedMolecules(std::ostream &output, std::string suffix)
346{
347 const std::vector<const molecule *> molecules =
348 const_cast<const World &>(World::getInstance()).getSelectedMolecules();
349 std::map<size_t, const atom *> IdAtoms;
350 for (std::vector<const molecule *>::const_iterator MolIter = molecules.begin();
351 MolIter != molecules.end();
352 ++MolIter) {
353 for(molecule::const_iterator AtomIter = (*MolIter)->begin();
354 AtomIter != (*MolIter)->end();
355 ++AtomIter) {
356 IdAtoms.insert( make_pair((*AtomIter)->getId(), (*AtomIter)) );
357 }
358 }
359 std::vector<const atom *> atoms;
360 atoms.reserve(IdAtoms.size());
361 for (std::map<size_t, const atom *>::const_iterator iter = IdAtoms.begin();
362 iter != IdAtoms.end();
363 ++iter) {
364 atoms.push_back(iter->second);
365 }
366 return save(output, suffix, atoms);
367}
368
369/** Stores world in an ostream depending on its suffix
370 * \param &output output stream
371 * \param suffix
372 * \return true - storing ok, false - suffix unknown
373 */
374bool FormatParserStorage::saveWorld(std::ostream &output, std::string suffix)
375{
376 const std::vector<const atom *> atoms =
377 const_cast<const World &>(World::getInstance()).getAllAtoms();
378 return save(output, suffix, atoms);
379}
380
381/** Stores a given vector of \a atoms in an ostream depending on its suffix
382 * \param &output output stream
383 * \param suffix
384 * \return true - storing ok, false - suffix unknown
385 */
386bool FormatParserStorage::save(
387 std::ostream &output,
388 std::string suffix,
389 const std::vector<const atom *> &atoms)
390{
391 enum ParserTypes type = getTypeFromSuffix(suffix);
392 if (type != ParserTypes_end)
393 get(type).save(&output, atoms);
394 else
395 return false;
396 return true;
397}
398
399/** Returns reference to the desired output parser as FormatParser, adds if not present.
400 * \param _type type of desired parser
401 * \return reference to the output FormatParser with desired type
402 */
403FormatParserInterface &FormatParserStorage::get(ParserTypes _type)
404{
405 if (!ParserPresent[_type]) {
406 add(_type);
407 }
408 return *ParserList[_type];
409}
410
411CONSTRUCT_SINGLETON(FormatParserStorage)
Note: See TracBrowser for help on using the repository browser.