Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-2018 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed 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 Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #include "IFile.h"
23 : #include "Exception.h"
24 : #include "core/Action.h"
25 : #include "core/PlumedMain.h"
26 : #include "core/Value.h"
27 : #include "Communicator.h"
28 : #include "Tools.h"
29 : #include <cstdarg>
30 : #include <cstring>
31 : #include <cmath>
32 :
33 : #include <iostream>
34 : #include <string>
35 : #ifdef __PLUMED_HAS_ZLIB
36 : #include <zlib.h>
37 : #endif
38 :
39 : namespace PLMD {
40 :
41 5752751 : size_t IFile::llread(char*ptr,size_t s) {
42 5752751 : plumed_assert(fp);
43 : size_t r;
44 5752751 : if(gzfp) {
45 : #ifdef __PLUMED_HAS_ZLIB
46 3438 : int rr=gzread(gzFile(gzfp),ptr,s);
47 3438 : if(rr==0) eof=true;
48 3438 : if(rr<0) err=true;
49 3438 : r=rr;
50 : #else
51 : plumed_merror("file " + getPath() + ": trying to use a gz file without zlib being linked");
52 : #endif
53 : } else {
54 5749313 : r=fread(ptr,1,s,fp);
55 5749313 : if(feof(fp)) eof=true;
56 5749313 : if(ferror(fp)) err=true;
57 : }
58 5752751 : return r;
59 : }
60 :
61 66360 : IFile& IFile::advanceField() {
62 66360 : plumed_assert(!inMiddleOfField);
63 66360 : std::string line;
64 66360 : bool done=false;
65 193773 : while(!done) {
66 67118 : getline(line);
67 67118 : if(!*this) {return *this;}
68 61053 : std::vector<std::string> words=Tools::getWords(line);
69 61053 : if(words.size()>=2 && words[0]=="#!" && words[1]=="FIELDS") {
70 62 : fields.clear();
71 512 : for(unsigned i=2; i<words.size(); i++) {
72 450 : Field field;
73 450 : field.name=words[i];
74 450 : fields.push_back(field);
75 450 : }
76 60991 : } else if(words.size()==4 && words[0]=="#!" && words[1]=="SET") {
77 160 : Field field;
78 160 : field.name=words[2];
79 160 : field.value=words[3];
80 160 : field.constant=true;
81 160 : fields.push_back(field);
82 : } else {
83 60831 : unsigned nf=0;
84 60831 : for(unsigned i=0; i<fields.size(); i++) if(!fields[i].constant) nf++;
85 60831 : Tools::trimComments(line);
86 60831 : words=Tools::getWords(line);
87 60831 : if( words.size()==nf ) {
88 60295 : unsigned j=0;
89 817965 : for(unsigned i=0; i<fields.size(); i++) {
90 757670 : if(fields[i].constant) continue;
91 325546 : fields[i].value=words[j];
92 325546 : fields[i].read=false;
93 325546 : j++;
94 : }
95 60295 : done=true;
96 536 : } else if( !words.empty() ) {
97 0 : plumed_merror("file " + getPath() + ": mismatch between number of fields in file and expected number");
98 : }
99 : }
100 61053 : }
101 60295 : inMiddleOfField=true;
102 60295 : return *this;
103 : }
104 :
105 372 : IFile& IFile::open(const std::string&path) {
106 372 : plumed_massert(!cloned,"file "+path+" appears to be cloned");
107 372 : eof=false;
108 372 : err=false;
109 372 : fp=NULL;
110 372 : gzfp=NULL;
111 372 : bool do_exist=FileExist(path);
112 372 : plumed_massert(do_exist,"file " + path + " cannot be found");
113 372 : fp=std::fopen(const_cast<char*>(this->path.c_str()),"r");
114 372 : if(Tools::extension(this->path)=="gz") {
115 : #ifdef __PLUMED_HAS_ZLIB
116 6 : gzfp=(void*)gzopen(const_cast<char*>(this->path.c_str()),"r");
117 : #else
118 : plumed_merror("file " + getPath() + ": trying to use a gz file without zlib being linked");
119 : #endif
120 : }
121 372 : if(plumed) plumed->insertFile(*this);
122 372 : return *this;
123 : }
124 :
125 34623 : IFile& IFile::scanFieldList(std::vector<std::string>&s) {
126 34623 : if(!inMiddleOfField) advanceField();
127 34623 : if(!*this) return *this;
128 34623 : s.clear();
129 401354 : for(unsigned i=0; i<fields.size(); i++)
130 366731 : s.push_back(fields[i].name);
131 34623 : return *this;
132 : }
133 :
134 34610 : bool IFile::FieldExist(const std::string& s) {
135 34610 : std::vector<std::string> slist;
136 34610 : scanFieldList(slist);
137 34610 : int mycount = (int) std::count(slist.begin(), slist.end(), s);
138 34610 : if(mycount>0) return true;
139 20667 : else return false;
140 : }
141 :
142 763083 : IFile& IFile::scanField(const std::string&name,std::string&str) {
143 763083 : if(!inMiddleOfField) advanceField();
144 763083 : if(!*this) return *this;
145 757018 : unsigned i=findField(name);
146 757018 : str=fields[i].value;
147 757018 : fields[i].read=true;
148 757018 : return *this;
149 : }
150 :
151 326025 : IFile& IFile::scanField(const std::string&name,double &x) {
152 326025 : std::string str;
153 326025 : scanField(name,str);
154 326025 : if(*this) Tools::convert(str,x);
155 326025 : return *this;
156 : }
157 :
158 100795 : IFile& IFile::scanField(const std::string&name,int &x) {
159 100795 : std::string str;
160 100795 : scanField(name,str);
161 100795 : if(*this) Tools::convert(str,x);
162 100795 : return *this;
163 : }
164 :
165 9126 : IFile& IFile::scanField(Value* val) {
166 9126 : double ff=NAN; // this is to be sure a NAN value is replaced upon failure
167 9126 : scanField( val->getName(), ff );
168 9126 : val->set( ff );
169 9126 : if( FieldExist("min_" + val->getName() ) ) {
170 0 : std::string min, max;
171 0 : scanField("min_" + val->getName(), min );
172 0 : scanField("max_" + val->getName(), max );
173 0 : val->setDomain( min, max );
174 : } else {
175 9126 : val->setNotPeriodic();
176 : }
177 9126 : return *this;
178 : }
179 :
180 60299 : IFile& IFile::scanField() {
181 60299 : if(!ignoreFields) {
182 733441 : for(unsigned i=0; i<fields.size(); i++) {
183 679811 : plumed_massert(fields[i].read,"field "+fields[i].name+" was not read: all the fields need to be read otherwise you could miss important infos" );
184 : }
185 : }
186 60299 : inMiddleOfField=false;
187 60299 : return *this;
188 : }
189 :
190 457 : IFile::IFile():
191 : inMiddleOfField(false),
192 : ignoreFields(false),
193 457 : noEOL(false)
194 : {
195 457 : }
196 :
197 1465 : IFile::~IFile() {
198 445 : if(inMiddleOfField) std::cerr<<"WARNING: IFile closed in the middle of reading. seems strange!\n";
199 1020 : }
200 :
201 73408 : IFile& IFile::getline(std::string &str) {
202 73408 : char tmp=0;
203 73408 : str="";
204 : fpos_t pos;
205 73408 : fgetpos(fp,&pos);
206 5826154 : while(llread(&tmp,1)==1 && tmp && tmp!='\n' && tmp!='\r' && !eof && !err) {
207 5679338 : str+=tmp;
208 : }
209 73408 : if(tmp=='\r') {
210 5 : llread(&tmp,1);
211 5 : plumed_massert(tmp=='\n',"plumed only accepts \\n (unix) or \\r\\n (dos) new lines");
212 : }
213 73408 : if(eof && noEOL) {
214 209 : if(str.length()>0) eof=false;
215 73199 : } else if(eof || err || tmp!='\n') {
216 6068 : eof = true;
217 6068 : str="";
218 6068 : if(!err) fsetpos(fp,&pos);
219 : // there was a fsetpos here that apparently is not necessary
220 : // fsetpos(fp,&pos);
221 : // I think it was necessary to have rewind working correctly
222 : // after end of file. Since rewind is not used now anywhere,
223 : // it should be ok not to reset position.
224 : // This is necessary so that eof works properly for emacs files
225 : // with no endline at end of file.
226 : }
227 73408 : return *this;
228 : }
229 :
230 757018 : unsigned IFile::findField(const std::string&name)const {
231 : unsigned i;
232 757018 : for(i=0; i<fields.size(); i++) if(fields[i].name==name) break;
233 757018 : if(i>=fields.size()) {
234 0 : plumed_merror("file " + getPath() + ": field " + name + " cannot be found");
235 : }
236 757018 : return i;
237 : }
238 :
239 6058 : void IFile::reset(bool reset) {
240 6058 : eof = reset;
241 6058 : err = reset;
242 6058 : if(!reset && fp) clearerr(fp);
243 : #ifdef __PLUMED_HAS_ZLIB
244 6058 : if(!reset && gzfp) gzclearerr(gzFile(gzfp));
245 : #endif
246 6058 : return;
247 : }
248 :
249 5566 : void IFile::allowIgnoredFields() {
250 5566 : ignoreFields=true;
251 5566 : }
252 :
253 296 : void IFile::allowNoEOL() {
254 296 : noEOL=true;
255 296 : }
256 :
257 2523 : }
|