diff --git a/applications/test/token/Test-token.C b/applications/test/token/Test-token.C index dfdb5bb0e028ff2f872cc8bf20beb728f1a0e7a9..628b964360b8c9be98b77ed9e20c2e4c34874a11 100644 --- a/applications/test/token/Test-token.C +++ b/applications/test/token/Test-token.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2017 OpenCFD Ltd. + Copyright (C) 2017-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -33,6 +33,7 @@ Description #include "IFstream.H" #include "StringStream.H" #include "cpuTime.H" +#include "labelList.H" #include "DynamicList.H" using namespace Foam; @@ -71,6 +72,47 @@ int main(int argc, char *argv[]) Info<< "assign token: " << tok3.info() << endl; Info<< "orig: " << tok4.info() << endl; + // + // Compound + // + + { + // This version is good + + token ctok1(new token::Compound<labelList>(identity(10))); + + Info<< "compound token: " << ctok1.info() << nl << ctok1 << endl; + } + + { + // This also works, but not actually using the autoPtr directly + + autoPtr<token::Compound<labelList>> ptr + ( + new token::Compound<labelList>(identity(10, -9)) + ); + + token ctok1(ptr.release()); // release() not get()! + + Info<< "compound token: " << ctok1.info() << nl << ctok1 << endl; + } + + #if 0 + { + // This version will segfault. + // The implicit pointer cast from autoPtr to pointer wracks havoc + + autoPtr<token::Compound<labelList>> ptr + ( + new token::Compound<labelList>(identity(10)) + ); + + token ctok1(ptr); + + Info<< "compound token: " << ctok1.info() << nl << ctok1 << endl; + } + #endif + return 0; } diff --git a/src/OpenFOAM/db/IOstreams/token/token.C b/src/OpenFOAM/db/IOstreams/token/token.C index 5039206407df13da48f069097cbe1044d78ea1c0..6eac51cc1f7e2cda71cbc1564aa53d1ffb9e877d 100644 --- a/src/OpenFOAM/db/IOstreams/token/token.C +++ b/src/OpenFOAM/db/IOstreams/token/token.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2019 OpenCFD Ltd. + Copyright (C) 2017-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -87,25 +87,46 @@ bool Foam::token::compound::isCompound(const word& name) } +Foam::token::compound& Foam::token::transferCompoundToken() +{ + if (type_ != tokenType::COMPOUND) + { + parseError("compound"); + } + + if (data_.compoundPtr->empty()) + { + FatalErrorInFunction + << "compound has already been transferred from token\n " + << info() << abort(FatalError); + } + else + { + data_.compoundPtr->empty() = true; + } + + return *data_.compoundPtr; +} + + Foam::token::compound& Foam::token::transferCompoundToken(const Istream& is) { - if (type_ == tokenType::COMPOUND) + if (type_ != tokenType::COMPOUND) + { + parseError("compound"); + } + + if (data_.compoundPtr->empty()) + { + FatalIOErrorInFunction(is) + << "compound has already been transferred from token\n " + << info() << abort(FatalIOError); + } + else { - if (data_.compoundPtr->empty()) - { - FatalIOErrorInFunction(is) - << "compound has already been transferred from token\n " - << info() << abort(FatalIOError); - } - else - { - data_.compoundPtr->empty() = true; - } - - return *data_.compoundPtr; + data_.compoundPtr->empty() = true; } - parseError("compound"); return *data_.compoundPtr; } diff --git a/src/OpenFOAM/db/IOstreams/token/token.H b/src/OpenFOAM/db/IOstreams/token/token.H index 8e401fd6d4eef249c62310a54ba30445a0625995..407a1c74c2db6c534326343bb805e9f7ad660110 100644 --- a/src/OpenFOAM/db/IOstreams/token/token.H +++ b/src/OpenFOAM/db/IOstreams/token/token.H @@ -62,7 +62,6 @@ namespace Foam class token; Ostream& operator<<(Ostream& os, const token& tok); - /*---------------------------------------------------------------------------*\ Class token Declaration \*---------------------------------------------------------------------------*/ @@ -178,39 +177,40 @@ public: // Constructors //- Default construct - compound() + constexpr compound() noexcept : empty_(false) {} - - // Selectors - - //- Select null constructed + //- Construct compound from Istream static autoPtr<compound> New(const word& type, Istream& is); - //- Return true if name is a known (registered) compound type - static bool isCompound(const word& name); - //- Destructor - virtual ~compound() = default; + virtual ~compound() noexcept = default; // Member Functions - bool empty() const + //- Test if name is a known (registered) compound type + static bool isCompound(const word& name); + + //- Has compound been transferred? + bool empty() const noexcept { return empty_; } - bool& empty() + //- Access to empty + bool& empty() noexcept { return empty_; } + //- The size of the underlying content virtual label size() const = 0; + //- Redirect write to underlying content virtual void write(Ostream& os) const = 0; @@ -233,20 +233,43 @@ public: //- Declare type-name, virtual type (with debug switch) TypeName("Compound<T>"); - Compound(Istream& is) - : - T(is) - {} + // Constructors - label size() const - { - return T::size(); - } + //- Copy construct + explicit Compound(const T& val) + : + T(val) + {} - void write(Ostream& os) const - { - operator<<(os, static_cast<const T&>(*this)); - } + //- Move construct + explicit Compound(T&& val) + : + T(std::move(val)) + {} + + //- Read construct from Istream + explicit Compound(Istream& is) + : + T(is) + {} + + + // Member Functions + + //- Using empty from compound refCount + using token::compound::empty; + + //- The size of the underlying content + virtual label size() const + { + return T::size(); + } + + //- Redirect write to underlying content + virtual void write(Ostream& os) const + { + operator<<(os, static_cast<const T&>(*this)); + } }; @@ -286,13 +309,13 @@ private: tokenType type_; //- Line number in the file the token was read from - label lineNumber_; + label line_; // Private Member Functions //- Set as UNDEFINED and zero the union content without any checking - inline void setUndefined(); + inline void setUndefined() noexcept; // Parse error, expected 'expected', found ... void parseError(const char* expected) const; @@ -315,31 +338,34 @@ public: inline token(const token& t); //- Move construct. The original token is left as UNDEFINED. - inline token(token&& t); + inline token(token&& t) noexcept; //- Construct punctuation character token - inline explicit token(punctuationToken p, label lineNumber=0); + inline explicit token(punctuationToken p, label lineNum=0) noexcept; //- Construct label token - inline explicit token(const label val, label lineNumber=0); + inline explicit token(const label val, label lineNum=0) noexcept; //- Construct float token - inline explicit token(const floatScalar val, label lineNumber=0); + inline explicit token(const floatScalar val, label lineNum=0) noexcept; //- Construct double token - inline explicit token(const doubleScalar val, label lineNumber=0); + inline explicit token(const doubleScalar val, label lineNum=0) noexcept; //- Copy construct word token - inline explicit token(const word& w, label lineNumber=0); + inline explicit token(const word& w, label lineNum=0); //- Copy construct string token - inline explicit token(const string& str, label lineNumber=0); + inline explicit token(const string& str, label lineNum=0); //- Move construct word token - inline explicit token(word&& w, label lineNumber=0); + inline explicit token(word&& w, label lineNum=0); //- Move construct string token - inline explicit token(string&& str, label lineNumber=0); + inline explicit token(string&& str, label lineNum=0); + + //- Construct from a compound pointer, taking ownership + inline explicit token(token::compound* ptr, label lineNum=0); //- Construct from Istream explicit token(Istream& is); @@ -352,12 +378,12 @@ public: // Static Functions //- Create a bool token. - inline static token boolean(bool on); + inline static token boolean(bool on) noexcept; //- Create a token with stream flags, no sanity check // // \param bitmask the flags to set - inline static token flag(int bitmask); + inline static token flag(int bitmask) noexcept; //- True if the character is a punctuation separator (eg, in ISstream). // Since it could also start a number, SUBTRACT is not included as @@ -365,7 +391,7 @@ public: // // \param c the character to test, passed as int for consistency with // isdigit, isspace etc. - inline static bool isseparator(int c); + inline static bool isseparator(int c) noexcept; // Member Functions @@ -376,7 +402,7 @@ public: word name() const; //- Return the token type - inline tokenType type() const; + inline tokenType type() const noexcept; //- Change the token type, for similar types. // This can be used to change between string-like variants @@ -385,70 +411,70 @@ public: // use the corresponding assignment operator. // // \return true if the change was successful or no change was required - inline bool setType(const tokenType tokType); + inline bool setType(const tokenType tokType) noexcept; //- The line number for the token - inline label lineNumber() const; + inline label lineNumber() const noexcept; //- The line number for the token - inline label& lineNumber(); + inline label& lineNumber() noexcept; //- True if token is not UNDEFINED or ERROR - inline bool good() const; + inline bool good() const noexcept; //- Token is UNDEFINED - inline bool undefined() const; + inline bool undefined() const noexcept; //- Token is ERROR - inline bool error() const; + inline bool error() const noexcept; //- Token is BOOL - inline bool isBool() const; + inline bool isBool() const noexcept; //- Token is FLAG - inline bool isFlag() const; + inline bool isFlag() const noexcept; //- Token is PUNCTUATION - inline bool isPunctuation() const; + inline bool isPunctuation() const noexcept; //- Token is PUNCTUATION and isseparator - inline bool isSeparator() const; + inline bool isSeparator() const noexcept; //- Token is LABEL - inline bool isLabel() const; + inline bool isLabel() const noexcept; //- Token is FLOAT - inline bool isFloat() const; + inline bool isFloat() const noexcept; //- Token is DOUBLE - inline bool isDouble() const; + inline bool isDouble() const noexcept; //- Token is FLOAT or DOUBLE - inline bool isScalar() const; + inline bool isScalar() const noexcept; //- Token is LABEL, FLOAT or DOUBLE - inline bool isNumber() const; + inline bool isNumber() const noexcept; //- Token is WORD or DIRECTIVE word - inline bool isWord() const; + inline bool isWord() const noexcept; //- Token is DIRECTIVE (word variant) - inline bool isDirective() const; + inline bool isDirective() const noexcept; //- Token is STRING, VARIABLE or VERBATIM string - inline bool isString() const; + inline bool isString() const noexcept; //- Token is VARIABLE (string variant) - inline bool isVariable() const; + inline bool isVariable() const noexcept; //- Token is VERBATIM string (string variant) - inline bool isVerbatim() const; + inline bool isVerbatim() const noexcept; //- Token is WORD, DIRECTIVE, STRING, VARIABLE or VERBATIM - inline bool isStringType() const; + inline bool isStringType() const noexcept; //- Token is COMPOUND - inline bool isCompound() const; + inline bool isCompound() const noexcept; // Access @@ -500,8 +526,10 @@ public: //- Read access for compound token inline const compound& compoundToken() const; - //- Return reference to compound token and decrease its internal - //- refCount accordingly. + //- Return reference to compound and mark internally as \em released. + compound& transferCompoundToken(); + + //- Return reference to compound and mark internally as \em released. // The Istream is used for reference error messages only. compound& transferCompoundToken(const Istream& is); @@ -562,7 +590,10 @@ public: inline void operator=(string&& str); //- Assign compound with reference counting to token - inline void operator=(compound* compoundPtr); + inline void operator=(token::compound* ptr); + + //- Move assign from compound pointer + inline void operator=(autoPtr<token::compound>&& ptr); // Equality diff --git a/src/OpenFOAM/db/IOstreams/token/tokenI.H b/src/OpenFOAM/db/IOstreams/token/tokenI.H index 60b772aa919e8bb9f88eb6e95fdb4c8ed80f934c..eda92d596808c341589c25f474c2e8e67b3a3649 100644 --- a/src/OpenFOAM/db/IOstreams/token/tokenI.H +++ b/src/OpenFOAM/db/IOstreams/token/tokenI.H @@ -30,7 +30,7 @@ License // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // -inline Foam::token Foam::token::boolean(bool on) +inline Foam::token Foam::token::boolean(bool on) noexcept { token tok; tok.type_ = tokenType::BOOL; @@ -40,7 +40,7 @@ inline Foam::token Foam::token::boolean(bool on) } -inline Foam::token Foam::token::flag(int bitmask) +inline Foam::token Foam::token::flag(int bitmask) noexcept { token tok; tok.type_ = tokenType::FLAG; @@ -50,7 +50,7 @@ inline Foam::token Foam::token::flag(int bitmask) } -inline bool Foam::token::isseparator(int c) +inline bool Foam::token::isseparator(int c) noexcept { // NOTE: keep synchronized with ISstream::read(token&) @@ -84,7 +84,7 @@ inline bool Foam::token::isseparator(int c) // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -inline void Foam::token::setUndefined() +inline void Foam::token::setUndefined() noexcept { type_ = tokenType::UNDEFINED; data_.int64Val = 0; // bit-wise zero for union content @@ -98,7 +98,7 @@ inline constexpr Foam::token::token() noexcept : data_(), // bit-wise zero for union content type_(tokenType::UNDEFINED), - lineNumber_(0) + line_(0) {} @@ -106,7 +106,7 @@ inline Foam::token::token(const token& tok) : data_(tok.data_), // bit-wise copy of union content type_(tok.type_), - lineNumber_(tok.lineNumber_) + line_(tok.line_) { // Fundamental: values already handled by bit-wise copy // Pointer: duplicate content or increase refCount @@ -142,97 +142,107 @@ inline Foam::token::token(const token& tok) } -inline Foam::token::token(token&& tok) +inline Foam::token::token(token&& tok) noexcept : data_(tok.data_), // bit-wise copy of union content type_(tok.type_), - lineNumber_(tok.lineNumber_) + line_(tok.line_) { tok.setUndefined(); // zero the union content without any checking - tok.lineNumber_ = 0; + tok.line_ = 0; } -inline Foam::token::token(punctuationToken p, label lineNumber) +inline Foam::token::token(punctuationToken p, label lineNum) noexcept : data_(), type_(tokenType::PUNCTUATION), - lineNumber_(lineNumber) + line_(lineNum) { data_.punctuationVal = p; } -inline Foam::token::token(const label val, label lineNumber) +inline Foam::token::token(const label val, label lineNum) noexcept : data_(), type_(tokenType::LABEL), - lineNumber_(lineNumber) + line_(lineNum) { data_.labelVal = val; } -inline Foam::token::token(const floatScalar val, label lineNumber) +inline Foam::token::token(const floatScalar val, label lineNum) noexcept : data_(), type_(tokenType::FLOAT), - lineNumber_(lineNumber) + line_(lineNum) { data_.floatVal = val; } -inline Foam::token::token(const doubleScalar val, label lineNumber) +inline Foam::token::token(const doubleScalar val, label lineNum) noexcept : data_(), type_(tokenType::DOUBLE), - lineNumber_(lineNumber) + line_(lineNum) { data_.doubleVal = val; } -inline Foam::token::token(const word& w, label lineNumber) +inline Foam::token::token(const word& w, label lineNum) : data_(), type_(tokenType::WORD), - lineNumber_(lineNumber) + line_(lineNum) { data_.wordPtr = new word(w); } -inline Foam::token::token(const string& str, label lineNumber) +inline Foam::token::token(const string& str, label lineNum) : data_(), type_(tokenType::STRING), - lineNumber_(lineNumber) + line_(lineNum) { data_.stringPtr = new string(str); } -inline Foam::token::token(word&& w, label lineNumber) +inline Foam::token::token(word&& w, label lineNum) : data_(), type_(tokenType::WORD), - lineNumber_(lineNumber) + line_(lineNum) { data_.wordPtr = new word(std::move(w)); } -inline Foam::token::token(string&& str, label lineNumber) +inline Foam::token::token(string&& str, label lineNum) : data_(), type_(tokenType::STRING), - lineNumber_(lineNumber) + line_(lineNum) { data_.stringPtr = new string(std::move(str)); } +inline Foam::token::token(token::compound* ptr, label lineNum) +: + data_(), + type_(tokenType::COMPOUND), + line_(lineNum) +{ + data_.compoundPtr = ptr; +} + + // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // inline Foam::token::~token() @@ -292,17 +302,17 @@ inline void Foam::token::swap(token& tok) std::swap(data_, tok.data_); std::swap(type_, tok.type_); - std::swap(lineNumber_, tok.lineNumber_); + std::swap(line_, tok.line_); } -inline Foam::token::tokenType Foam::token::type() const +inline Foam::token::tokenType Foam::token::type() const noexcept { return type_; } -inline bool Foam::token::setType(token::tokenType tokType) +inline bool Foam::token::setType(token::tokenType tokType) noexcept { if (type_ == tokType) { @@ -374,37 +384,37 @@ inline bool Foam::token::setType(token::tokenType tokType) } -inline Foam::label Foam::token::lineNumber() const +inline Foam::label Foam::token::lineNumber() const noexcept { - return lineNumber_; + return line_; } -inline Foam::label& Foam::token::lineNumber() +inline Foam::label& Foam::token::lineNumber() noexcept { - return lineNumber_; + return line_; } -inline bool Foam::token::good() const +inline bool Foam::token::good() const noexcept { return (type_ != tokenType::UNDEFINED && type_ != tokenType::ERROR); } -inline bool Foam::token::undefined() const +inline bool Foam::token::undefined() const noexcept { return (type_ == tokenType::UNDEFINED); } -inline bool Foam::token::error() const +inline bool Foam::token::error() const noexcept { return (type_ == tokenType::ERROR); } -inline bool Foam::token::isBool() const +inline bool Foam::token::isBool() const noexcept { return (type_ == tokenType::BOOL); } @@ -422,7 +432,7 @@ inline bool Foam::token::boolToken() const } -inline bool Foam::token::isFlag() const +inline bool Foam::token::isFlag() const noexcept { return (type_ == tokenType::FLAG); } @@ -440,7 +450,7 @@ inline int Foam::token::flagToken() const } -inline bool Foam::token::isPunctuation() const +inline bool Foam::token::isPunctuation() const noexcept { return (type_ == tokenType::PUNCTUATION); } @@ -458,7 +468,7 @@ inline Foam::token::punctuationToken Foam::token::pToken() const } -inline bool Foam::token::isSeparator() const +inline bool Foam::token::isSeparator() const noexcept { return ( @@ -468,7 +478,7 @@ inline bool Foam::token::isSeparator() const } -inline bool Foam::token::isLabel() const +inline bool Foam::token::isLabel() const noexcept { return (type_ == tokenType::LABEL); } @@ -486,7 +496,7 @@ inline Foam::label Foam::token::labelToken() const } -inline bool Foam::token::isFloat() const +inline bool Foam::token::isFloat() const noexcept { return (type_ == tokenType::FLOAT); } @@ -504,7 +514,7 @@ inline Foam::floatScalar Foam::token::floatToken() const } -inline bool Foam::token::isDouble() const +inline bool Foam::token::isDouble() const noexcept { return (type_ == tokenType::DOUBLE); } @@ -522,7 +532,7 @@ inline Foam::doubleScalar Foam::token::doubleToken() const } -inline bool Foam::token::isScalar() const +inline bool Foam::token::isScalar() const noexcept { return ( @@ -548,7 +558,7 @@ inline Foam::scalar Foam::token::scalarToken() const } -inline bool Foam::token::isNumber() const +inline bool Foam::token::isNumber() const noexcept { return (type_ == tokenType::LABEL || isScalar()); } @@ -570,7 +580,7 @@ inline Foam::scalar Foam::token::number() const } -inline bool Foam::token::isWord() const +inline bool Foam::token::isWord() const noexcept { return ( @@ -580,7 +590,7 @@ inline bool Foam::token::isWord() const } -inline bool Foam::token::isDirective() const +inline bool Foam::token::isDirective() const noexcept { return (type_ == tokenType::DIRECTIVE); } @@ -602,7 +612,7 @@ inline const Foam::word& Foam::token::wordToken() const } -inline bool Foam::token::isString() const +inline bool Foam::token::isString() const noexcept { return ( @@ -613,19 +623,19 @@ inline bool Foam::token::isString() const } -inline bool Foam::token::isVariable() const +inline bool Foam::token::isVariable() const noexcept { return (type_ == tokenType::VARIABLE); } -inline bool Foam::token::isVerbatim() const +inline bool Foam::token::isVerbatim() const noexcept { return (type_ == tokenType::VERBATIM); } -inline bool Foam::token::isStringType() const +inline bool Foam::token::isStringType() const noexcept { return (isWord() || isString()); } @@ -657,7 +667,7 @@ inline const Foam::string& Foam::token::stringToken() const } -inline bool Foam::token::isCompound() const +inline bool Foam::token::isCompound() const noexcept { return (type_ == tokenType::COMPOUND); } @@ -695,7 +705,7 @@ inline void Foam::token::operator=(const token& tok) type_ = tok.type_; data_ = tok.data_; // bit-wise copy of union content - lineNumber_ = tok.lineNumber_; + line_ = tok.line_; // Fundamental: values already handled by bit-wise copy // Pointer: duplicate content or increase refCount @@ -739,7 +749,7 @@ inline void Foam::token::operator=(token&& tok) } reset(); - lineNumber_ = 0; + line_ = 0; swap(tok); } @@ -808,11 +818,19 @@ inline void Foam::token::operator=(string&& s) } -inline void Foam::token::operator=(Foam::token::compound* compoundPtr) +inline void Foam::token::operator=(Foam::token::compound* ptr) +{ + reset(); + type_ = tokenType::COMPOUND; + data_.compoundPtr = ptr; +} + + +inline void Foam::token::operator=(autoPtr<token::compound>&& ptr) { reset(); type_ = tokenType::COMPOUND; - data_.compoundPtr = compoundPtr; + data_.compoundPtr = ptr.release(); }