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