openfoam/src/OpenFOAM/db/IOstreams/Fstreams/fstreamPointers.C
Mark Olesen 6e2b7be983 ENH: direct access to wrapped ifstream/ofstream with compression (#1805)
- previously hidden as Detail::[IO]FstreamAllocator, now exposed
  directly as [io]fstreamPointer, which allows reuse for
  std::ifstream, std::ofstream wrapping, without the additional
  ISstream, OSstream layers.

  These stream pointers have some characteristics similar to a
  unique_ptr.

- restrict direct gzstream usage to two files (fstreamPointers.C,
  gzstream.C) which improves localization and makes it simpler to
  enable/disable with the `HAVE_LIBZ` define.

  The HAVE_LIBZ define is currently simply hard-coded in the
  Make/options.

  If compiled WITHOUT libz support:
    - reading gz files : FatalError
    - writing gz files : emit warning and downgrade to uncompressed
    - warn if compression is specified in the case controlDict
      and downgrade to uncompressed

ENH: minor updates to gzstream interface for C++11

- support construct/open with std::string for the file names.

CONFIG: provisioning for have_libz detection as wmake/script
2020-08-10 12:40:08 +02:00

232 lines
5.6 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM 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 3 of the License, or
(at your option) any later version.
OpenFOAM 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 General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "fstreamPointer.H"
#include "OSspecific.H"
// HAVE_LIBZ defined externally
// #define HAVE_LIBZ
#ifdef HAVE_LIBZ
#include "gzstream.h"
#endif /* HAVE_LIBZ */
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
static inline void removeConflictingFiles
(
const fileName& otherName,
const bool append,
const fileName& targetName
)
{
// Remove other (compressed/uncompressed) version
const fileName::Type pathType = Foam::type(otherName, false);
if (pathType == fileName::FILE || pathType == fileName::LINK)
{
Foam::rm(otherName);
}
// Disallow writing into symlinked files.
// Eg, avoid problems with symlinked initial fields
if (!append && Foam::type(targetName) == fileName::LINK)
{
Foam::rm(targetName);
}
}
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
bool Foam::ifstreamPointer::supports_gz()
{
#ifdef HAVE_LIBZ
return true;
#else
return false;
#endif
}
bool Foam::ofstreamPointer::supports_gz()
{
#ifdef HAVE_LIBZ
return true;
#else
return false;
#endif
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::ifstreamPointer::ifstreamPointer
(
const fileName& pathname
)
:
ptr_(nullptr)
{
const std::ios_base::openmode mode
(
std::ios_base::in | std::ios_base::binary
);
ptr_.reset(new std::ifstream(pathname, mode));
if (!ptr_->good())
{
// Try compressed version instead
const fileName pathname_gz(pathname + ".gz");
if (isFile(pathname_gz, false))
{
#ifdef HAVE_LIBZ
ptr_.reset(new igzstream(pathname_gz, mode));
#else /* HAVE_LIBZ */
FatalError
<< "No read support for gz compressed files (libz)"
<< " : could use 'gunzip' from the command-line" << nl
<< "file: " << pathname_gz << endl
<< exit(FatalError);
#endif /* HAVE_LIBZ */
}
}
}
Foam::ofstreamPointer::ofstreamPointer
(
const fileName& pathname,
IOstreamOption::compressionType comp,
const bool append
)
:
ptr_(nullptr)
{
std::ios_base::openmode mode
(
std::ios_base::out | std::ios_base::binary
);
if (append)
{
mode |= std::ios_base::app;
}
const fileName pathname_gz(pathname + ".gz");
if (IOstreamOption::COMPRESSED == comp)
{
// Output compression requested
#ifdef HAVE_LIBZ
removeConflictingFiles(pathname, append, pathname_gz);
ptr_.reset(new ogzstream(pathname_gz, mode));
#else /* HAVE_LIBZ */
comp = IOstreamOption::UNCOMPRESSED;
Warning
<< nl
<< "No write support for gz compressed files (libz)"
<< " : downgraded to UNCOMPRESSED" << nl
<< "file: " << pathname_gz << endl;
#endif /* HAVE_LIBZ */
}
if (IOstreamOption::UNCOMPRESSED == comp)
{
removeConflictingFiles(pathname_gz, append, pathname);
ptr_.reset(new std::ofstream(pathname, mode));
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::ifstreamPointer::reopen_gz(const fileName& pathname_gz)
{
#ifdef HAVE_LIBZ
igzstream* gz = dynamic_cast<igzstream*>(ptr_.get());
if (gz)
{
// Special treatment for gzstream
gz->close();
gz->clear();
gz->open(pathname_gz);
}
#endif /* HAVE_LIBZ */
}
Foam::IOstreamOption::compressionType
Foam::ifstreamPointer::whichCompression() const
{
#ifdef HAVE_LIBZ
if (dynamic_cast<const igzstream*>(ptr_.get()))
{
return IOstreamOption::compressionType::COMPRESSED;
}
#endif /* HAVE_LIBZ */
return IOstreamOption::compressionType::UNCOMPRESSED;
}
Foam::IOstreamOption::compressionType
Foam::ofstreamPointer::whichCompression() const
{
#ifdef HAVE_LIBZ
if (dynamic_cast<const ogzstream*>(ptr_.get()))
{
return IOstreamOption::compressionType::COMPRESSED;
}
#endif /* HAVE_LIBZ */
return IOstreamOption::compressionType::UNCOMPRESSED;
}
// ************************************************************************* //