ENH: add read/write specialization for lists of character data

- read/write lists of character data in binary only.
  This is the only means of preserving data.
  If character data are written as an ASCII list, there is no means of
  determining if spaces or newlines are content or separators.
This commit is contained in:
Mark Olesen 2021-02-26 18:41:33 +01:00 committed by Andrew Heather
parent 498de8a74a
commit e3c8af0c8f
13 changed files with 558 additions and 6 deletions

View File

@ -0,0 +1,3 @@
Test-charList.C
EXE = $(FOAM_USER_APPBIN)/Test-charList

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -0,0 +1,87 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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/>.
Application
Test-charList
Description
Some test of UList, List for characters
\*---------------------------------------------------------------------------*/
#include "OSspecific.H"
#include "argList.H"
#include "IOstreams.H"
#include "messageStream.H"
#include "charList.H"
#include "labelList.H"
#include "StringStream.H"
#include "ListOps.H"
#include "SubList.H"
#include "FlatOutput.H"
#include <numeric>
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noBanner();
argList::noParallel();
argList::noFunctionObjects();
#include "setRootCase.H"
Info<< "Known compound tokens: "
<< token::compound::IstreamConstructorTablePtr_->sortedToc() << nl;
OStringStream ostr;
{
List<char> alphabet(64);
std::iota(alphabet.begin(), alphabet.end(), '@');
alphabet.writeEntry("alphabet", Info);
ostr << alphabet;
Info<< "wrote: " << ostr.str() << nl;
}
{
IStringStream istr(ostr.str());
List<char> alphabet(istr);
Info<< "re-read: " << alphabet << nl;
}
return 0;
}
// ************************************************************************* //

View File

@ -31,8 +31,10 @@ $(bools)/Switch/Switch.C
$(bools)/lists/boolList.C
chars = primitives/chars
$(chars)/char/charIO.C
$(chars)/wchar/wcharIO.C
$(chars)/char/char.C
$(chars)/wchar/wchar.C
$(chars)/lists/charList.C
$(chars)/lists/charUList.C
primitives/direction/directionIO.C

View File

@ -353,6 +353,14 @@ public:
};
// * * * * * * * * * * * * Template Specializations * * * * * * * * * * * * //
//- Specialized list reading for character lists which always uses
//- binary format.
template<>
Istream& List<char>::readList(Istream& is);
// * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * //
//- Create identity map of the given length with (map[i] == i)

View File

@ -551,6 +551,24 @@ public:
};
// * * * * * * * * * * * * Template Specializations * * * * * * * * * * * * //
//- Specialized list reading for character lists which always uses
//- binary format.
template<>
Istream& UList<char>::readList(Istream& is);
//- Specialized writeEntry for character lists which always uses
//- binary format.
template<>
void UList<char>::writeEntry(Ostream& os) const;
//- Specialized writeList for character lists which always uses
//- binary format.
template<>
Ostream& UList<char>::writeList(Ostream& os, const label /*unused*/) const;
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
//- Write List to Ostream, as per UList::writeList() with default length.

View File

@ -5,7 +5,8 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -30,6 +31,20 @@ License
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
const char* const Foam::pTraits<char>::typeName = "char";
Foam::pTraits<char>::pTraits(const char p) noexcept
:
p_(p)
{}
Foam::pTraits<char>::pTraits(Istream& is)
{
is >> p_;
}
char Foam::readChar(Istream& is)
{
char c;

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -30,7 +31,7 @@ Description
A character and a pointer to a character string.
SourceFiles
charIO.C
char.C
\*---------------------------------------------------------------------------*/
@ -42,6 +43,7 @@ SourceFiles
namespace Foam
{
// Forward Declarations
class Istream;
class Ostream;
@ -59,7 +61,7 @@ Ostream& operator<<(Ostream& os, const char c);
//- Write a nul-terminated C-string
Ostream& operator<<(Ostream& os, const char* str);
//- Test for \em horizontal whitespace
//- Test for whitespace
inline bool isspace(char c)
{
return
@ -72,6 +74,55 @@ inline bool isspace(char c)
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "pTraits.H"
namespace Foam
{
// Template specialisation for pTraits<char>
template<>
class pTraits<char>
{
char p_;
public:
// Static Data Members
static const char* const typeName;
// Constructors
//- Copy construct from primitive
explicit pTraits(const char p) noexcept;
//- Read construct from Istream
explicit pTraits(Istream& is);
// Member Functions
//- Read access to primitive value
operator char() const noexcept
{
return p_;
}
//- Write access to primitive value
operator char&() noexcept
{
return p_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -0,0 +1,116 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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 "charList.H"
#include "Istream.H"
#include "Ostream.H"
#include "token.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineCompoundTypeName(List<char>, charList);
addCompoundToRunTimeSelectionTable(List<char>, charList);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
namespace Foam
{
template<>
Istream& List<char>::readList(Istream& is)
{
List<char>& list = *this;
// Anull list
list.clear();
is.fatalCheck(FUNCTION_NAME);
token tok(is);
is.fatalCheck("List<char>::readList(Istream&) : reading first token");
if (tok.isCompound())
{
// Compound: simply transfer contents
list.transfer
(
dynamicCast<token::Compound<List<char>>>
(
tok.transferCompoundToken(is)
)
);
}
else if (tok.isLabel())
{
// Label: could be int(..) or just a plain '0'
const label len = tok.labelToken();
// Resize to actual length read
list.resize(len);
// Binary, always contiguous
if (len)
{
const auto oldFmt = is.format(IOstream::BINARY);
// read(...) includes surrounding start/end delimiters
is.read(list.data(), std::streamsize(len));
is.format(oldFmt);
is.fatalCheck
(
"List<char>::readList(Istream&) : "
"reading binary block"
);
}
}
else
{
FatalIOErrorInFunction(is)
<< "incorrect first token, expected <int>, found "
<< tok.info() << nl
<< exit(FatalIOError);
}
return is;
}
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,56 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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/>.
Typedef
Foam::charListList
Description
A List of charList.
\*---------------------------------------------------------------------------*/
#ifndef charList_H
#define charList_H
#include "char.H"
#include "List.H"
#include "SubList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// charUList = defined in UList.H
// charList = defined in List.H
// charSubList = defined in SubList.H
typedef List<charList> charListList;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,193 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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 "charList.H"
#include "Istream.H"
#include "Ostream.H"
#include "token.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
static Ostream& writeChars
(
Ostream& os,
const char* chars,
std::streamsize count
)
{
// Contents are binary and contiguous
os << nl << label(count) << nl;
if (count)
{
const auto oldFmt = os.format(IOstream::BINARY);
// write(...) includes surrounding start/end delimiters
os.write(chars, count);
os.format(oldFmt);
}
os.check(FUNCTION_NAME);
return os;
}
} // End namespace Foam
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
namespace Foam
{
template<>
void UList<char>::writeEntry(Ostream& os) const
{
const std::streamsize count(this->size());
os << word("List<char>");
if (count)
{
writeChars(os, this->cdata(), count);
}
else
{
// Zero-sized binary - Write size only
os << token::SPACE << label(0);
}
}
} // End namespace Foam
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
namespace Foam
{
template<>
Ostream& UList<char>::writeList
(
Ostream& os,
const label /* shortLen (unused) */
) const
{
return writeChars(os, this->cdata(), std::streamsize(this->size()));
}
template<>
Istream& UList<char>::readList(Istream& is)
{
UList<char>& list = *this;
// The target list length - must match with sizes read
const label len = list.size();
is.fatalCheck(FUNCTION_NAME);
token tok(is);
is.fatalCheck("UList<char>::readList(Istream&) : reading first token");
if (tok.isCompound())
{
// Compound: simply transfer contents
List<char> elems;
elems.transfer
(
dynamicCast<token::Compound<List<char>>>
(
tok.transferCompoundToken(is)
)
);
const label inputLen = elems.size();
// List lengths must match
if (inputLen != len)
{
FatalIOErrorInFunction(is)
<< "incorrect length for UList. Read "
<< inputLen << " expected " << len
<< exit(FatalIOError);
}
this->deepCopy(elems);
}
if (tok.isLabel())
{
// Label: could be int(..) or just a plain '0'
const label inputLen = tok.labelToken();
// List lengths must match
if (inputLen != len)
{
FatalIOErrorInFunction(is)
<< "incorrect length for UList. Read "
<< inputLen << " expected " << len
<< exit(FatalIOError);
}
// Binary, always contiguous
if (len)
{
const auto oldFmt = is.format(IOstream::BINARY);
// read(...) includes surrounding start/end delimiters
is.read(list.data(), std::streamsize(len));
is.format(oldFmt);
is.fatalCheck
(
"UList<char>::readList(Istream&) : "
"reading binary block"
);
}
}
else
{
FatalIOErrorInFunction(is)
<< "incorrect first token, expected <int>, found "
<< tok.info() << nl
<< exit(FatalIOError);
}
return is;
}
} // End namespace Foam
// ************************************************************************* //

View File

@ -30,7 +30,7 @@ Description
A wide-character and a pointer to a wide-character string.
SourceFiles
wcharIO.C
wchar.C
See also
http://en.wikipedia.org/wiki/UTF-8
@ -49,6 +49,7 @@ See also
namespace Foam
{
// Forward Declarations
class Istream;
class Ostream;