Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2012-2023 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 "FileTools.h" 24 : #include "Exception.h" 25 : #include "core/Action.h" 26 : #include "core/PlumedMain.h" 27 : #include "core/Value.h" 28 : #include "Communicator.h" 29 : #include "Tools.h" 30 : #include <cstdarg> 31 : #include <cstring> 32 : #include <cstdlib> 33 : 34 : #include <string> 35 : 36 : #ifdef __PLUMED_HAS_ZLIB 37 : #include <zlib.h> 38 : #endif 39 : 40 : namespace PLMD { 41 : 42 12158 : FileBase& FileBase::link(FILE*newfp) { 43 12158 : plumed_massert(!fp,"cannot link an already open file"); 44 12158 : fp=newfp; 45 12158 : cloned=true; 46 12158 : return *this; 47 : } 48 : 49 10303 : FileBase& FileBase::flush() { 50 10303 : if(fp) { 51 10253 : fflush(fp); 52 : } 53 10303 : return *this; 54 : } 55 : 56 817619 : FileBase& FileBase::link(Communicator&setcomm) { 57 817619 : plumed_massert(!fp,"cannot link an already open file"); 58 817619 : comm=&setcomm; 59 817619 : return *this; 60 : } 61 : 62 7312 : FileBase& FileBase::link(PlumedMain&plumedmain) { 63 7312 : plumed_massert(!fp,"cannot link an already open file"); 64 7312 : plumed=&plumedmain; 65 7312 : link(plumed->comm); 66 7312 : return *this; 67 : } 68 : 69 5863 : FileBase& FileBase::link(Action&actiontolink) { 70 5863 : plumed_massert(!fp,"cannot link an already open file"); 71 5863 : action=&actiontolink; 72 5863 : link(action->plumed); 73 5863 : return *this; 74 : } 75 : 76 3055 : bool FileBase::FileExist(const std::string& setpath) { 77 : bool do_exist=false; 78 3055 : path=appendSuffix(setpath,getSuffix()); 79 3055 : mode="r"; 80 : // first try with suffix 81 3055 : unique_FILE ff(std::fopen(path.c_str(),"r")); 82 3055 : if(!ff) { 83 : path=setpath; 84 : // then try without suffix 85 : // (the unique_FILE also closes this second file, which was leaked until v2.10) 86 759 : ff.reset(std::fopen(path.c_str(),"r")); 87 : mode="r"; 88 : } 89 3055 : if(ff) { 90 : do_exist=true; 91 : } 92 3055 : if(comm) { 93 2668 : comm->Barrier(); 94 : } 95 3055 : return do_exist; 96 : } 97 : 98 825710 : bool FileBase::isOpen() { 99 : bool isopen=false; 100 825710 : if(fp) { 101 : isopen=true; 102 : } 103 825710 : return isopen; 104 : } 105 : 106 1357 : void FileBase::close() { 107 1357 : plumed_assert(!cloned); 108 1357 : eof=false; 109 1357 : err=false; 110 1357 : if(fp) { 111 1347 : std::fclose(fp); 112 : } 113 : #ifdef __PLUMED_HAS_ZLIB 114 1357 : if(gzfp) { 115 5 : gzclose(gzFile(gzfp)); 116 : } 117 : #endif 118 1357 : fp=NULL; 119 1357 : gzfp=NULL; 120 1357 : } 121 : 122 829410 : FileBase::FileBase(): 123 829410 : fp(NULL), 124 829410 : gzfp(NULL), 125 829410 : comm(NULL), 126 829410 : plumed(NULL), 127 829410 : action(NULL), 128 829410 : cloned(false), 129 829410 : eof(false), 130 829410 : err(false), 131 829410 : heavyFlush(false), 132 829410 : enforcedSuffix_(false) { 133 829410 : } 134 : 135 829406 : FileBase::~FileBase() { 136 829406 : if(plumed) { 137 7312 : plumed->eraseFile(*this); 138 : } 139 829406 : if(!cloned && fp) { 140 6135 : std::fclose(fp); 141 : } 142 : #ifdef __PLUMED_HAS_ZLIB 143 829406 : if(!cloned && gzfp) { 144 28 : gzclose(gzFile(gzfp)); 145 : } 146 : #endif 147 829406 : } 148 : 149 32644313 : FileBase::operator bool()const { 150 32644313 : return !eof; 151 : } 152 : 153 9684 : std::string FileBase::appendSuffix(const std::string&path,const std::string&suffix) { 154 9684 : if(path=="/dev/null") { 155 330 : return path; // do not append a suffix to /dev/null 156 : } 157 9354 : std::string ret=path; 158 9354 : std::string ext=Tools::extension(path); 159 : 160 : // These are the recognized extensions so far: 161 : // gz xtc trr 162 : // If a file name ends with one of these extensions, the suffix is added *before* 163 : // the extension. This is useful when extensions are conventionally used 164 : // to detect file type, so as to allow easier file manipulation. 165 : // Removing this line, any extension recognized by Tools::extension() would be considered 166 : // if(ext!="gz" && ext!="xtc" && ext!="trr") ext=""; 167 : 168 9354 : if(ext.length()>0) { 169 5932 : int l=path.length()-(ext.length()+1); 170 5932 : plumed_assert(l>=0); 171 5932 : ret.resize(l); 172 : } 173 : ret+=suffix; 174 9354 : if(ext.length()>0) { 175 5932 : ret+="."+ext; 176 : } 177 9354 : return ret; 178 5932 : } 179 : 180 714 : FileBase& FileBase::enforceSuffix(const std::string&suffix) { 181 714 : enforcedSuffix_=true; 182 714 : enforcedSuffix=suffix; 183 714 : return *this; 184 : } 185 : 186 8347 : std::string FileBase::getSuffix()const { 187 8347 : if(enforcedSuffix_) { 188 744 : return enforcedSuffix; 189 : } 190 7603 : if(plumed) { 191 6753 : return plumed->getSuffix(); 192 : } 193 850 : return ""; 194 : } 195 : 196 : }