mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: add failsafe accessors for ITstream
- failsafe examine elements: peek(), peekFirst(), peekLast()
- failsafe traversing: skip()
For example,
ITstream& is = dict.lookup(key);
if (is.peek().isWord())
{
is.skip();
}
This commit is contained in:
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2017 OpenCFD Ltd.
|
Copyright (C) 2017-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -78,7 +78,7 @@ void printTokens(Istream& is)
|
|||||||
if (t.good())
|
if (t.good())
|
||||||
{
|
{
|
||||||
++count;
|
++count;
|
||||||
Info<<"token: " << t << endl;
|
Info<< "token: " << t << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,14 +86,28 @@ void printTokens(Istream& is)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class BUF>
|
Ostream& reportPeek(const ITstream& is)
|
||||||
void doTest(const string& name, const BUF& input, bool verbose=false)
|
|
||||||
{
|
{
|
||||||
Info<<"test " << name.c_str() << ":" << nl
|
Info<< " index : " << is.tokenIndex() << nl
|
||||||
<<"====" << nl;
|
<< " peek : " << is.peek().info() << nl;
|
||||||
|
return Info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class BUF>
|
||||||
|
void doTest
|
||||||
|
(
|
||||||
|
const string& name,
|
||||||
|
const BUF& input,
|
||||||
|
bool verbose = false,
|
||||||
|
bool testskip = false
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Info<< "test " << name.c_str() << ":" << nl
|
||||||
|
<< "====" << nl;
|
||||||
toString(Info, input)
|
toString(Info, input)
|
||||||
<< nl
|
<< nl
|
||||||
<<"====" << nl << endl;
|
<< "====" << nl << endl;
|
||||||
|
|
||||||
ITstream its(name, input);
|
ITstream its(name, input);
|
||||||
Info<< "got " << its.size() << " tokens - index at "
|
Info<< "got " << its.size() << " tokens - index at "
|
||||||
@ -107,6 +121,35 @@ void doTest(const string& name, const BUF& input, bool verbose=false)
|
|||||||
}
|
}
|
||||||
Info<< nl;
|
Info<< nl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (testskip)
|
||||||
|
{
|
||||||
|
Info<< " first : " << its.peekFirst().info() << nl
|
||||||
|
<< " last : " << its.peekLast().info() << nl;
|
||||||
|
|
||||||
|
Info<< "rewind():" << nl;
|
||||||
|
reportPeek(its);
|
||||||
|
|
||||||
|
its.skip(3);
|
||||||
|
Info<< "skip(3):" << nl;
|
||||||
|
reportPeek(its);
|
||||||
|
|
||||||
|
its.skip(2);
|
||||||
|
Info<< "skip(2):" << nl;
|
||||||
|
reportPeek(its);
|
||||||
|
|
||||||
|
its.skip(-2);
|
||||||
|
Info<< "skip(-2):" << nl;
|
||||||
|
reportPeek(its);
|
||||||
|
|
||||||
|
its.skip(100);
|
||||||
|
Info<< "skip(100):" << nl;
|
||||||
|
reportPeek(its);
|
||||||
|
|
||||||
|
its.skip(-1000);
|
||||||
|
Info<< "skip(-1000):" << nl;
|
||||||
|
reportPeek(its);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -116,14 +159,16 @@ void doTest(const string& name, const BUF& input, bool verbose=false)
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const char* charInput =
|
const char* charInput =
|
||||||
"( const char input \"string\" to tokenize )"
|
"( const char input \"string\" to tokenize )\n"
|
||||||
"List<label> 5(0 1 2 3 4);";
|
"List<label> 5(0 1 2 3 4);";
|
||||||
|
|
||||||
string stringInput("( string ; input \"string\" to tokenize )");
|
string stringInput("( string ; input \"string\" to tokenize )");
|
||||||
|
|
||||||
List<char> listInput(stringInput.cbegin(), stringInput.cend());
|
List<char> listInput(stringInput.cbegin(), stringInput.cend());
|
||||||
|
|
||||||
doTest("char*", charInput, true);
|
doTest("empty", "", true, true);
|
||||||
|
|
||||||
|
doTest("char*", charInput, true, true);
|
||||||
doTest("string", stringInput, true);
|
doTest("string", stringInput, true);
|
||||||
doTest("List<char>", listInput, true);
|
doTest("List<char>", listInput, true);
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,31 @@ License
|
|||||||
#include "StringStream.H"
|
#include "StringStream.H"
|
||||||
#include "UIListStream.H"
|
#include "UIListStream.H"
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
// Failsafe read-access.
|
||||||
|
// Return the token at location, or undefinedToken.
|
||||||
|
inline static const Foam::token& peekTokenAt
|
||||||
|
(
|
||||||
|
const Foam::UList<Foam::token>& list,
|
||||||
|
const Foam::label i
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
i >= 0 && i < list.size()
|
||||||
|
? list[i]
|
||||||
|
: Foam::token::undefinedToken
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::label Foam::ITstream::parseStream(ISstream& is, tokenList& tokens)
|
Foam::label Foam::ITstream::parseStream(ISstream& is, tokenList& tokens)
|
||||||
@ -270,20 +295,21 @@ void Foam::ITstream::print(Ostream& os) const
|
|||||||
{
|
{
|
||||||
os << "ITstream : " << name_.c_str() << ", line ";
|
os << "ITstream : " << name_.c_str() << ", line ";
|
||||||
|
|
||||||
if (size())
|
const tokenList& toks = *this;
|
||||||
{
|
|
||||||
os << tokenList::first().lineNumber();
|
|
||||||
|
|
||||||
if (tokenList::first().lineNumber() < tokenList::last().lineNumber())
|
if (toks.empty())
|
||||||
{
|
|
||||||
os << '-' << tokenList::last().lineNumber();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
os << lineNumber();
|
os << lineNumber();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
os << toks.first().lineNumber();
|
||||||
|
|
||||||
|
if (toks.first().lineNumber() < toks.last().lineNumber())
|
||||||
|
{
|
||||||
|
os << '-' << toks.last().lineNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
os << ", ";
|
os << ", ";
|
||||||
|
|
||||||
IOstream::print(os);
|
IOstream::print(os);
|
||||||
@ -292,44 +318,155 @@ void Foam::ITstream::print(Ostream& os) const
|
|||||||
|
|
||||||
std::string Foam::ITstream::toString() const
|
std::string Foam::ITstream::toString() const
|
||||||
{
|
{
|
||||||
OStringStream buf;
|
|
||||||
|
|
||||||
const tokenList& tokens = *this;
|
|
||||||
|
|
||||||
label len = tokens.size();
|
|
||||||
|
|
||||||
// NOTE: may wish to have special handling if there is a single token
|
// NOTE: may wish to have special handling if there is a single token
|
||||||
// and it is already a string or word
|
// and it is already a string or word
|
||||||
|
|
||||||
for (const token& tok : tokens)
|
OStringStream buf;
|
||||||
|
unsigned i = 0;
|
||||||
|
for (const token& tok : *this)
|
||||||
{
|
{
|
||||||
buf << tok;
|
if (i++)
|
||||||
|
|
||||||
if (--len)
|
|
||||||
{
|
{
|
||||||
buf << ' ';
|
buf << ' ';
|
||||||
}
|
}
|
||||||
|
buf << tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::token& Foam::ITstream::peekFirst() const
|
||||||
|
{
|
||||||
|
return peekTokenAt(*this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::token& Foam::ITstream::peekLast() const
|
||||||
|
{
|
||||||
|
return peekTokenAt(*this, tokenList::size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::token& Foam::ITstream::peek() const
|
||||||
|
{
|
||||||
|
// Use putback token if it exists
|
||||||
|
if (Istream::hasPutback())
|
||||||
|
{
|
||||||
|
return Istream::peekBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
return peekTokenAt(*this, tokenIndex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ITstream::seek(label pos)
|
||||||
|
{
|
||||||
|
lineNumber_ = 0;
|
||||||
|
const tokenList& toks = *this;
|
||||||
|
const label nToks = toks.size();
|
||||||
|
|
||||||
|
if (!pos)
|
||||||
|
{
|
||||||
|
// Seek begin (rewind)
|
||||||
|
tokenIndex_ = 0;
|
||||||
|
|
||||||
|
if (nToks)
|
||||||
|
{
|
||||||
|
lineNumber_ = toks.first().lineNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpened();
|
||||||
|
setGood();
|
||||||
|
}
|
||||||
|
else if (pos < 0 || pos >= nToks)
|
||||||
|
{
|
||||||
|
// Seek end or seek is out of range
|
||||||
|
tokenIndex_ = nToks;
|
||||||
|
|
||||||
|
if (nToks)
|
||||||
|
{
|
||||||
|
lineNumber_ = toks.last().lineNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
setEof();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Seek middle (from the beginning)
|
||||||
|
tokenIndex_ = pos;
|
||||||
|
|
||||||
|
if (nToks)
|
||||||
|
{
|
||||||
|
lineNumber_ = toks[tokenIndex_].lineNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpened();
|
||||||
|
setGood();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ITstream::skip(label n)
|
||||||
|
{
|
||||||
|
const tokenList& toks = *this;
|
||||||
|
const label nToks = toks.size();
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
// Move backwards
|
||||||
|
while (n++ && tokenIndex_)
|
||||||
|
{
|
||||||
|
--tokenIndex_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenIndex_ < nToks)
|
||||||
|
{
|
||||||
|
lineNumber_ = toks[tokenIndex_].lineNumber();
|
||||||
|
setOpened();
|
||||||
|
setGood();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (n > 0)
|
||||||
|
{
|
||||||
|
// Move forward
|
||||||
|
while (n-- && tokenIndex_ < nToks)
|
||||||
|
{
|
||||||
|
++tokenIndex_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenIndex_ < nToks)
|
||||||
|
{
|
||||||
|
lineNumber_ = toks[tokenIndex_].lineNumber();
|
||||||
|
setOpened();
|
||||||
|
setGood();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setEof();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::Istream& Foam::ITstream::read(token& tok)
|
Foam::Istream& Foam::ITstream::read(token& tok)
|
||||||
{
|
{
|
||||||
// Return the put back token if it exists
|
// Use putback token if it exists
|
||||||
if (Istream::getBack(tok))
|
if (Istream::getBack(tok))
|
||||||
{
|
{
|
||||||
lineNumber_ = tok.lineNumber();
|
lineNumber_ = tok.lineNumber();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenIndex_ < size())
|
tokenList& toks = *this;
|
||||||
|
const label nToks = toks.size();
|
||||||
|
|
||||||
|
if (tokenIndex_ < nToks)
|
||||||
{
|
{
|
||||||
tok = operator[](tokenIndex_++);
|
tok = toks[tokenIndex_++];
|
||||||
lineNumber_ = tok.lineNumber();
|
lineNumber_ = tok.lineNumber();
|
||||||
|
|
||||||
if (tokenIndex_ == size())
|
if (tokenIndex_ == nToks)
|
||||||
{
|
{
|
||||||
setEof();
|
setEof();
|
||||||
}
|
}
|
||||||
@ -350,9 +487,9 @@ Foam::Istream& Foam::ITstream::read(token& tok)
|
|||||||
|
|
||||||
tok.reset();
|
tok.reset();
|
||||||
|
|
||||||
if (size())
|
if (nToks)
|
||||||
{
|
{
|
||||||
tok.lineNumber(tokenList::last().lineNumber());
|
tok.lineNumber(toks.last().lineNumber());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -426,52 +563,6 @@ void Foam::ITstream::rewind()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::ITstream::seek(label pos)
|
|
||||||
{
|
|
||||||
lineNumber_ = 0;
|
|
||||||
tokenList& toks = *this;
|
|
||||||
|
|
||||||
if (!pos)
|
|
||||||
{
|
|
||||||
// Seek begin (rewind)
|
|
||||||
tokenIndex_ = 0;
|
|
||||||
|
|
||||||
if (!toks.empty())
|
|
||||||
{
|
|
||||||
lineNumber_ = toks.first().lineNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
setOpened();
|
|
||||||
setGood();
|
|
||||||
}
|
|
||||||
else if (pos < 0 || pos >= toks.size())
|
|
||||||
{
|
|
||||||
// Seek end or seek is out of range
|
|
||||||
tokenIndex_ = toks.size();
|
|
||||||
|
|
||||||
if (!toks.empty())
|
|
||||||
{
|
|
||||||
lineNumber_ = toks.last().lineNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
setEof();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Seek middle (from the beginning)
|
|
||||||
tokenIndex_ = pos;
|
|
||||||
|
|
||||||
if (!toks.empty())
|
|
||||||
{
|
|
||||||
lineNumber_ = toks[tokenIndex_].lineNumber();
|
|
||||||
}
|
|
||||||
|
|
||||||
setOpened();
|
|
||||||
setGood();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::ITstream::append(const token& t, const bool lazy)
|
void Foam::ITstream::append(const token& t, const bool lazy)
|
||||||
{
|
{
|
||||||
reserveCapacity(tokenIndex_ + 1, lazy);
|
reserveCapacity(tokenIndex_ + 1, lazy);
|
||||||
|
|||||||
@ -187,29 +187,49 @@ public:
|
|||||||
|
|
||||||
// Token Access
|
// Token Access
|
||||||
|
|
||||||
|
//- Failsafe peek at the \b first token in the list.
|
||||||
|
// \return \c undefinedToken if the list is empty.
|
||||||
|
const token& peekFirst() const;
|
||||||
|
|
||||||
|
//- Failsafe peek at the \b last token in the list.
|
||||||
|
// \return \c undefinedToken if the list is empty.
|
||||||
|
const token& peekLast() const;
|
||||||
|
|
||||||
|
//- Failsafe peek at what the next read would return,
|
||||||
|
// including handling of any putback
|
||||||
|
// \return \c undefinedToken if list is exhausted
|
||||||
|
const token& peek() const;
|
||||||
|
|
||||||
//- The current token index when reading, or the insertion point.
|
//- The current token index when reading, or the insertion point.
|
||||||
label tokenIndex() const
|
label tokenIndex() const noexcept
|
||||||
{
|
{
|
||||||
return tokenIndex_;
|
return tokenIndex_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Non-const access to the current token index
|
//- Non-const access to the current token index
|
||||||
label& tokenIndex()
|
label& tokenIndex() noexcept
|
||||||
{
|
{
|
||||||
return tokenIndex_;
|
return tokenIndex_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- The number of remaining tokens
|
//- Number of tokens remaining
|
||||||
label nRemainingTokens() const
|
label nRemainingTokens() const noexcept
|
||||||
{
|
{
|
||||||
return size() - tokenIndex_;
|
return size() - tokenIndex_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Move the tokenIndex to the specified position.
|
//- Move tokenIndex to the specified position
|
||||||
// Using seek(0) is identical to rewind.
|
// Using seek(0) is identical to rewind.
|
||||||
// Using seek(-1) moves to the end.
|
// Using seek(-1) moves to the end.
|
||||||
void seek(label pos);
|
void seek(label pos);
|
||||||
|
|
||||||
|
//- Move tokenIndex relative to the current position.
|
||||||
|
// Will not overrun the beginning or end positions.
|
||||||
|
//
|
||||||
|
// Use skip(2) to move forward two tokens.
|
||||||
|
// Use skip(-2) to move backward two tokens.
|
||||||
|
void skip(label n = 1);
|
||||||
|
|
||||||
|
|
||||||
// Inquiry
|
// Inquiry
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user