ENH: additional fstream pointer constructors with IOstreamOption

- allow future tweaking based on the target stream format.

- add ifstreamPointer::open().
  Allows default construct followed by open()
This commit is contained in:
Mark Olesen
2023-08-28 09:52:48 +02:00
parent b66369fb37
commit 12916cd7a3
4 changed files with 228 additions and 136 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd. Copyright (C) 2017-2023 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -45,7 +45,7 @@ Foam::IFstream::IFstream
IOstreamOption streamOpt IOstreamOption streamOpt
) )
: :
Foam::ifstreamPointer(pathname), Foam::ifstreamPointer(pathname, streamOpt),
ISstream(*(ifstreamPointer::get()), pathname, streamOpt) ISstream(*(ifstreamPointer::get()), pathname, streamOpt)
{ {
IOstreamOption::compression(ifstreamPointer::whichCompression()); IOstreamOption::compression(ifstreamPointer::whichCompression());

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd. Copyright (C) 2017-2023 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -65,7 +65,7 @@ Foam::OFstream::OFstream
Foam::ofstreamPointer Foam::ofstreamPointer
( (
pathname, pathname,
streamOpt.compression(), streamOpt,
(IOstreamOption::appendType::APPEND == append), (IOstreamOption::appendType::APPEND == append),
(IOstreamOption::atomicType::ATOMIC == atomic) (IOstreamOption::atomicType::ATOMIC == atomic)
), ),

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2020-2022 OpenCFD Ltd. Copyright (C) 2020-2023 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -74,7 +74,7 @@ class ifstreamPointer
{ {
// Private Data // Private Data
//- The stream pointer (ifstream or igzstream) //- The stream pointer (ifstream | igzstream, ...)
std::unique_ptr<std::istream> ptr_; std::unique_ptr<std::istream> ptr_;
@ -114,8 +114,20 @@ public:
//- Construct from pathname. //- Construct from pathname.
// Attempts to read the specified file. // Attempts to read the specified file.
// If that fails, try as a compressed file (.gz ending). // If that fails, try as a compressed file (.gz ending).
// \param pathname The file name to open for reading
explicit ifstreamPointer(const fileName& pathname); explicit ifstreamPointer(const fileName& pathname);
//- Construct from pathname, option.
// Attempts to read the specified file.
// If that fails, try as a compressed file (.gz ending).
// \param pathname The file name to open for reading
// \param streamOpt Currently unused
ifstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt
);
// Member Functions // Member Functions
@ -125,6 +137,9 @@ public:
// Access // Access
//- True if it holds a valid pointer
explicit operator bool() const noexcept { return bool(ptr_); }
//- The stream pointer (ifstream or igzstream) //- The stream pointer (ifstream or igzstream)
std::istream* get() noexcept { return ptr_.get(); } std::istream* get() noexcept { return ptr_.get(); }
@ -135,6 +150,19 @@ public:
IOstreamOption::compressionType whichCompression() const; IOstreamOption::compressionType whichCompression() const;
// Wrapped Methods
//- Attempts to open the specified file for reading.
// If that fails, try as a compressed file (.gz ending).
// \param pathname The file name to open for reading
// \param streamOpt Currently unused
void open
(
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption()
);
// Edit // Edit
//- Return managed pointer and release ownership //- Return managed pointer and release ownership
@ -168,7 +196,7 @@ class ofstreamPointer
{ {
// Private Data // Private Data
//- The stream pointer (ofstream | ogzstream | ocountstream) //- The stream pointer (ofstream | ogzstream | ocountstream, ...)
std::unique_ptr<std::ostream> ptr_; std::unique_ptr<std::ostream> ptr_;
//- Atomic file creation //- Atomic file creation
@ -211,9 +239,24 @@ public:
//- Default construct (empty) //- Default construct (empty)
ofstreamPointer() noexcept; ofstreamPointer() noexcept;
//- Construct as null output stream using Foam::ocountstream //- Construct as null output stream (Foam::ocountstream)
explicit ofstreamPointer(std::nullptr_t); explicit ofstreamPointer(std::nullptr_t);
//- Construct from pathname, option, append, file handling atomic
// \param pathname The file name to open for writing
// \param streamOpt Respects (UNCOMPRESSED | COMPRESSED)
// \param append Open in append mode
// \param atomic Write into temporary file (not target file).
// This option should only be used with a stream wrapper
// (eg, OFstream) that handles the final renaming.
explicit ofstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
const bool append = false,
const bool atomic = false
);
//- Construct from pathname, compression, append, file handling atomic //- Construct from pathname, compression, append, file handling atomic
// \param pathname The file name to open for writing // \param pathname The file name to open for writing
// \param comp UNCOMPRESSED | COMPRESSED // \param comp UNCOMPRESSED | COMPRESSED
@ -221,10 +264,10 @@ public:
// \param atomic Write into temporary file (not target file). // \param atomic Write into temporary file (not target file).
// This option should only be used with a stream wrapper // This option should only be used with a stream wrapper
// (eg, OFstream) that handles the final renaming. // (eg, OFstream) that handles the final renaming.
explicit ofstreamPointer ofstreamPointer
( (
const fileName& pathname, const fileName& pathname,
IOstreamOption::compressionType comp = IOstreamOption::UNCOMPRESSED, IOstreamOption::compressionType comp,
const bool append = false, const bool append = false,
const bool atomic = false const bool atomic = false
); );
@ -238,6 +281,9 @@ public:
// Access // Access
//- True if it holds a valid pointer
explicit operator bool() const noexcept { return bool(ptr_); }
//- The stream pointer (ofstream or ogzstream) //- The stream pointer (ofstream or ogzstream)
std::ostream* get() noexcept { return ptr_.get(); } std::ostream* get() noexcept { return ptr_.get(); }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018-2022 OpenCFD Ltd. Copyright (C) 2018-2023 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -60,8 +60,23 @@ bool Foam::ofstreamPointer::supports_gz()
} }
// Future: List<char> slurpFile(....);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::ifstreamPointer::ifstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt // Currently unused
)
:
ptr_(nullptr)
{
open(pathname, streamOpt);
}
Foam::ifstreamPointer::ifstreamPointer Foam::ifstreamPointer::ifstreamPointer
( (
const fileName& pathname const fileName& pathname
@ -69,6 +84,162 @@ Foam::ifstreamPointer::ifstreamPointer
: :
ptr_(nullptr) ptr_(nullptr)
{ {
open(pathname);
}
Foam::ofstreamPointer::ofstreamPointer() noexcept
:
ptr_(),
atomic_(false)
{}
Foam::ofstreamPointer::ofstreamPointer(std::nullptr_t)
:
ptr_(new Foam::ocountstream),
atomic_(false)
{}
Foam::ofstreamPointer::ofstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt,
const bool append,
const bool atomic
)
:
ptr_(nullptr),
atomic_(atomic)
{
std::ios_base::openmode mode
(
std::ios_base::out | std::ios_base::binary
);
if (append)
{
mode |= std::ios_base::app;
// Cannot append to gzstream
streamOpt.compression(IOstreamOption::UNCOMPRESSED);
// Cannot use append + atomic operation, without lots of extra work
atomic_ = false;
}
// When opening new files, remove file variants out of the way.
// Eg, opening "file1"
// - remove old "file1.gz" (compressed)
// - also remove old "file1" if it is a symlink and we are not appending
//
// Not writing into symlinked files avoids problems with symlinked
// initial fields (eg, 0/U -> ../0.orig/U)
const fileName pathname_gz(pathname + ".gz");
const fileName pathname_tmp(pathname + "~tmp~");
fileName::Type fType = fileName::Type::UNDEFINED;
if (IOstreamOption::COMPRESSED == streamOpt.compression())
{
// Output compression requested.
#ifdef HAVE_LIBZ
// TBD:
// atomic_ = true; // Always treat COMPRESSED like an atomic
const fileName& target = (atomic_ ? pathname_tmp : pathname_gz);
// Remove old uncompressed version (if any)
fType = Foam::type(pathname, false);
if (fType == fileName::SYMLINK || fType == fileName::FILE)
{
Foam::rm(pathname);
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
{
Foam::rm(target);
}
}
ptr_.reset(new ogzstream(target, mode));
#else /* HAVE_LIBZ */
streamOpt.compression(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::COMPRESSED != streamOpt.compression())
{
const fileName& target = (atomic_ ? pathname_tmp : pathname);
// Remove old compressed version (if any)
fType = Foam::type(pathname_gz, false);
if (fType == fileName::SYMLINK || fType == fileName::FILE)
{
Foam::rm(pathname_gz);
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
{
Foam::rm(target);
}
}
ptr_.reset(new std::ofstream(target, mode));
}
}
Foam::ofstreamPointer::ofstreamPointer
(
const fileName& pathname,
IOstreamOption::compressionType comp,
const bool append,
const bool atomic
)
:
ofstreamPointer
(
pathname,
IOstreamOption(IOstreamOption::ASCII, comp),
append,
atomic
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::ifstreamPointer::open
(
const fileName& pathname,
IOstreamOption streamOpt // Currently unused
)
{
// Forcibly close old stream (if any)
ptr_.reset(nullptr);
const std::ios_base::openmode mode const std::ios_base::openmode mode
( (
std::ios_base::in | std::ios_base::binary std::ios_base::in | std::ios_base::binary
@ -110,131 +281,6 @@ Foam::ifstreamPointer::ifstreamPointer
} }
Foam::ofstreamPointer::ofstreamPointer() noexcept
:
ptr_(),
atomic_(false)
{}
Foam::ofstreamPointer::ofstreamPointer(std::nullptr_t)
:
ptr_(new Foam::ocountstream),
atomic_(false)
{}
Foam::ofstreamPointer::ofstreamPointer
(
const fileName& pathname,
IOstreamOption::compressionType comp,
const bool append,
const bool atomic
)
:
ptr_(nullptr),
atomic_(atomic)
{
std::ios_base::openmode mode
(
std::ios_base::out | std::ios_base::binary
);
if (append)
{
mode |= std::ios_base::app;
// Cannot append to gzstream
comp = IOstreamOption::UNCOMPRESSED;
// Cannot use append + atomic operation, without lots of extra work
atomic_ = false;
}
// When opening new files, remove file variants out of the way.
// Eg, opening "file1"
// - remove old "file1.gz" (compressed)
// - also remove old "file1" if it is a symlink and we are not appending
//
// Not writing into symlinked files avoids problems with symlinked
// initial fields (eg, 0/U -> ../0.orig/U)
const fileName pathname_gz(pathname + ".gz");
const fileName pathname_tmp(pathname + "~tmp~");
fileName::Type fType = fileName::Type::UNDEFINED;
if (IOstreamOption::COMPRESSED == comp)
{
// Output compression requested.
#ifdef HAVE_LIBZ
// TBD:
// atomic_ = true; // Always treat COMPRESSED like an atomic
const fileName& target = (atomic_ ? pathname_tmp : pathname_gz);
// Remove old uncompressed version (if any)
fType = Foam::type(pathname, false);
if (fType == fileName::SYMLINK || fType == fileName::FILE)
{
Foam::rm(pathname);
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
{
Foam::rm(target);
}
}
ptr_.reset(new ogzstream(target, 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::COMPRESSED != comp)
{
const fileName& target = (atomic_ ? pathname_tmp : pathname);
// Remove old compressed version (if any)
fType = Foam::type(pathname_gz, false);
if (fType == fileName::SYMLINK || fType == fileName::FILE)
{
Foam::rm(pathname_gz);
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
{
Foam::rm(target);
}
}
ptr_.reset(new std::ofstream(target, mode));
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::ifstreamPointer::reopen_gz(const std::string& pathname) void Foam::ifstreamPointer::reopen_gz(const std::string& pathname)
{ {
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ