LCOV - code coverage report
Current view: top level - tools - IFile.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 143 149 96.0 %
Date: 2018-12-19 07:49:13 Functions: 20 22 90.9 %

          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 : }

Generated by: LCOV version 1.13