Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / utility / file.cpp
index 3fe2fbb461e6058a5013bda0d2798af674da2435..174fa00803bc8898cf4796b516944c64c8fd5516 100644 (file)
@@ -1,42 +1,50 @@
 /*
+ * This file is part of the GROMACS molecular simulation package.
  *
- *                This source code is part of
+ * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
  *
- *                 G   R   O   M   A   C   S
- *
- *          GROningen MAchine for Chemical Simulations
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
  *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
  *
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
  *
  * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
+ * the research papers on the package. Check out http://www.gromacs.org.
  */
 /*! \internal \file
  * \brief
  * Implements gmx::File.
  *
- * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \ingroup module_utility
  */
+#include "gmxpre.h"
+
 #include "file.h"
 
+#include "config.h"
+
 #include <cerrno>
 #include <cstdio>
 #include <cstring>
 #include <string>
 #include <vector>
 
+#include <sys/stat.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/gmxassert.h"
-#include "gromacs/utility/format.h"
+#include "gromacs/utility/stringutil.h"
 
 namespace gmx
 {
@@ -63,7 +77,7 @@ class File::Impl
         /*! \brief
          * Initialize a file object with the given handle.
          *
-         * \param[in]  fp     File handle to use (may be NULL).
+         * \param[in]  fp     %File handle to use (may be NULL).
          * \param[in]  bClose Whether this object should close its file handle.
          */
         Impl(FILE *fp, bool bClose);
@@ -120,7 +134,7 @@ void File::open(const char *filename, const char *mode)
 {
     GMX_RELEASE_ASSERT(impl_->fp_ == NULL,
                        "Attempted to open the same file object twice");
-    // TODO: Port all necessary functionality from ffopen() here.
+    // TODO: Port all necessary functionality from gmx_ffopen() here.
     impl_->fp_ = fopen(filename, mode);
     if (impl_->fp_ == NULL)
     {
@@ -150,6 +164,17 @@ void File::close()
     }
 }
 
+bool File::isInteractive() const
+{
+    GMX_RELEASE_ASSERT(impl_->fp_ != NULL,
+                       "Attempted to access a file object that is not open");
+#ifdef HAVE_UNISTD_H
+    return isatty(fileno(impl_->fp_));
+#else
+    return true;
+#endif
+}
+
 FILE *File::handle()
 {
     GMX_RELEASE_ASSERT(impl_->fp_ != NULL,
@@ -160,7 +185,7 @@ FILE *File::handle()
 void File::readBytes(void *buffer, size_t bytes)
 {
     errno = 0;
-    FILE *fp = handle();
+    FILE  *fp = handle();
     // TODO: Retry based on errno or something else?
     size_t bytesRead = std::fread(buffer, 1, bytes, fp);
     if (bytesRead != bytes)
@@ -168,11 +193,11 @@ void File::readBytes(void *buffer, size_t bytes)
         if (feof(fp))
         {
             GMX_THROW(FileIOError(
-                        formatString("Premature end of file\n"
-                                     "Attempted to read: %d bytes\n"
-                                     "Successfully read: %d bytes",
-                                     static_cast<int>(bytes),
-                                     static_cast<int>(bytesRead))));
+                              formatString("Premature end of file\n"
+                                           "Attempted to read: %d bytes\n"
+                                           "Successfully read: %d bytes",
+                                           static_cast<int>(bytes),
+                                           static_cast<int>(bytesRead))));
         }
         else
         {
@@ -182,6 +207,46 @@ void File::readBytes(void *buffer, size_t bytes)
     }
 }
 
+bool File::readLine(std::string *line)
+{
+    if (!readLineWithTrailingSpace(line))
+    {
+        return false;
+    }
+    size_t endPos = line->find_last_not_of(" \t\r\n");
+    if (endPos != std::string::npos)
+    {
+        line->resize(endPos + 1);
+    }
+    return true;
+}
+
+bool File::readLineWithTrailingSpace(std::string *line)
+{
+    line->clear();
+    const size_t bufsize = 256;
+    std::string  result;
+    char         buf[bufsize];
+    buf[0] = '\0';
+    FILE        *fp = handle();
+    while (fgets(buf, bufsize, fp) != NULL)
+    {
+        size_t length = std::strlen(buf);
+        result.append(buf, length);
+        if (length < bufsize - 1 || buf[length - 1] == '\n')
+        {
+            break;
+        }
+    }
+    if (ferror(fp))
+    {
+        GMX_THROW_WITH_ERRNO(FileIOError("Error while reading file"),
+                             "fgets", errno);
+    }
+    *line = result;
+    return !result.empty() || !feof(fp);
+}
+
 void File::writeString(const char *str)
 {
     if (fprintf(handle(), "%s", str) < 0)
@@ -207,6 +272,55 @@ void File::writeLine()
     writeString("\n");
 }
 
+// static
+bool File::exists(const char *filename)
+{
+    if (filename == NULL)
+    {
+        return false;
+    }
+    FILE *test = fopen(filename, "r");
+    if (test == NULL)
+    {
+        return false;
+    }
+    else
+    {
+        fclose(test);
+        // Windows doesn't allow fopen of directory, so we don't need to check
+        // this separately.
+#ifndef GMX_NATIVE_WINDOWS
+        struct stat st_buf;
+        int         status = stat(filename, &st_buf);
+        if (status != 0 || !S_ISREG(st_buf.st_mode))
+        {
+            return false;
+        }
+#endif
+        return true;
+    }
+}
+
+// static
+bool File::exists(const std::string &filename)
+{
+    return exists(filename.c_str());
+}
+
+// static
+File &File::standardInput()
+{
+    static File stdinObject(stdin, false);
+    return stdinObject;
+}
+
+// static
+File &File::standardOutput()
+{
+    static File stdoutObject(stdout, false);
+    return stdoutObject;
+}
+
 // static
 File &File::standardError()
 {
@@ -219,7 +333,7 @@ std::string File::readToString(const char *filename)
 {
     // Binary mode is required on Windows to be able to determine a size
     // that can be passed to fread().
-    File file(filename, "rb");
+    File  file(filename, "rb");
     FILE *fp = file.handle();
 
     if (std::fseek(fp, 0L, SEEK_END) != 0)
@@ -257,4 +371,12 @@ std::string File::readToString(const std::string &filename)
     return readToString(filename.c_str());
 }
 
+// static
+void File::writeFileFromString(const std::string &filename,
+                               const std::string &text)
+{
+    File file(filename, "w");
+    file.writeString(text);
+}
+
 } // namespace gmx