1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2    Copyright (c) 2012-2021 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 "FileBase.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 <cstdlib>
32 
33 #include <iostream>
34 #include <string>
35 
36 #ifdef __PLUMED_HAS_ZLIB
37 #include <zlib.h>
38 #endif
39 
40 namespace PLMD {
41 
link(FILE * fp)42 FileBase& FileBase::link(FILE*fp) {
43   plumed_massert(!this->fp,"cannot link an already open file");
44   this->fp=fp;
45   cloned=true;
46   return *this;
47 }
48 
flush()49 FileBase& FileBase::flush() {
50   if(fp) fflush(fp);
51   return *this;
52 }
53 
link(Communicator & comm)54 FileBase& FileBase::link(Communicator&comm) {
55   plumed_massert(!fp,"cannot link an already open file");
56   this->comm=&comm;
57   return *this;
58 }
59 
link(PlumedMain & plumed)60 FileBase& FileBase::link(PlumedMain&plumed) {
61   plumed_massert(!fp,"cannot link an already open file");
62   this->plumed=&plumed;
63   link(plumed.comm);
64   return *this;
65 }
66 
link(Action & action)67 FileBase& FileBase::link(Action&action) {
68   plumed_massert(!fp,"cannot link an already open file");
69   this->action=&action;
70   link(action.plumed);
71   return *this;
72 }
73 
FileExist(const std::string & path)74 bool FileBase::FileExist(const std::string& path) {
75   bool do_exist=false;
76   this->path=appendSuffix(path,getSuffix());
77   mode="r";
78   FILE *ff=std::fopen(const_cast<char*>(this->path.c_str()),"r");
79   if(!ff) {
80     this->path=path;
81     ff=std::fopen(const_cast<char*>(this->path.c_str()),"r");
82     mode="r";
83   }
84   if(ff) {do_exist=true; fclose(ff);}
85   if(comm) comm->Barrier();
86   return do_exist;
87 }
88 
isOpen()89 bool FileBase::isOpen() {
90   bool isopen=false;
91   if(fp) isopen=true;
92   return isopen;
93 }
94 
close()95 void        FileBase::close() {
96   plumed_assert(!cloned);
97   eof=false;
98   err=false;
99   if(fp)   std::fclose(fp);
100 #ifdef __PLUMED_HAS_ZLIB
101   if(gzfp) gzclose(gzFile(gzfp));
102 #endif
103   fp=NULL;
104   gzfp=NULL;
105 }
106 
FileBase()107 FileBase::FileBase():
108   fp(NULL),
109   gzfp(NULL),
110   comm(NULL),
111   plumed(NULL),
112   action(NULL),
113   cloned(false),
114   eof(false),
115   err(false),
116   heavyFlush(false),
117   enforcedSuffix_(false)
118 {
119 }
120 
~FileBase()121 FileBase::~FileBase()
122 {
123   if(plumed) plumed->eraseFile(*this);
124   if(!cloned && fp)   fclose(fp);
125 #ifdef __PLUMED_HAS_ZLIB
126   if(!cloned && gzfp) gzclose(gzFile(gzfp));
127 #endif
128 }
129 
operator bool() const130 FileBase::operator bool()const {
131   return !eof;
132 }
133 
appendSuffix(const std::string & path,const std::string & suffix)134 std::string FileBase::appendSuffix(const std::string&path,const std::string&suffix) {
135   if(path=="/dev/null") return path; // do not append a suffix to /dev/null
136   std::string ret=path;
137   std::string ext=Tools::extension(path);
138 
139 // These are the recognized extensions so far:
140 // gz xtc trr
141 // If a file name ends with one of these extensions, the suffix is added *before*
142 // the extension. This is useful when extensions are conventionally used
143 // to detect file type, so as to allow easier file manipulation.
144 // Removing this line, any extension recognized by Tools::extension() would be considered
145 //  if(ext!="gz" && ext!="xtc" && ext!="trr") ext="";
146 
147   if(ext.length()>0) {
148     int l=path.length()-(ext.length()+1);
149     plumed_assert(l>=0);
150     ret=ret.substr(0,l);
151   }
152   ret+=suffix;
153   if(ext.length()>0)ret+="."+ext;
154   return ret;
155 }
156 
enforceSuffix(const std::string & suffix)157 FileBase& FileBase::enforceSuffix(const std::string&suffix) {
158   enforcedSuffix_=true;
159   enforcedSuffix=suffix;
160   return *this;
161 }
162 
getSuffix() const163 std::string FileBase::getSuffix()const {
164   if(enforcedSuffix_) return enforcedSuffix;
165   if(plumed) return plumed->getSuffix();
166   return "";
167 }
168 
169 }
170