Commit 9087cd7b authored by Mark Olesen's avatar Mark Olesen
Browse files

Support for single-quoted strings

- token class handles both single and double quoted strings. Single quoted
  strings are used to tag regular expressions. At the moment this is just
  syntactical sugar and isn't (yet) treated differently than double-quoted
  strings.

- write output for std:string, with/without single quotes with the method
  writeQuoted(). Use distinct method name to avoid inadvertent compiler
  conversions.

- write wordRe and keyType using writeQuoted()
parent 96751f7e
......@@ -48,17 +48,11 @@ void Foam::Ostream::decrIndent()
// Write keyType
// write regular expression as single-quoted string
// write plain word as word (unquoted)
Foam::Ostream& Foam::Ostream::write(const keyType& kw)
{
// Write as word or string
if (kw.isPattern())
{
return write(static_cast<const string&>(kw));
}
else
{
return write(static_cast<const word&>(kw));
}
return writeQuoted(kw, kw.isPattern());
}
......@@ -76,6 +70,7 @@ Foam::Ostream& Foam::Ostream::writeKeyword(const keyType& kw)
nSpaces -= 2;
}
// could also increment by indentSize_ ...
if (nSpaces < 1)
{
nSpaces = 1;
......
......@@ -115,6 +115,14 @@ public:
//- Write string
virtual Ostream& write(const string&) = 0;
//- Write std::string surrounded by single quotes.
// Optional write without quotes.
virtual Ostream& writeQuoted
(
const std::string&,
const bool quoted=true
) = 0;
//- Write label
virtual Ostream& write(const label) = 0;
......
......@@ -175,6 +175,18 @@ Foam::Ostream& Foam::OPstream::write(const string& str)
}
Foam::Ostream& Foam::OPstream::writeQuoted(const std::string& str, const bool)
{
write(char(token::STRING));
size_t len = str.size();
writeToBuffer(len);
writeToBuffer(str.c_str(), len + 1, 1);
return *this;
}
Foam::Ostream& Foam::OPstream::write(const label val)
{
write(char(token::LABEL));
......
......@@ -136,6 +136,14 @@ public:
//- Write string
Ostream& write(const string&);
//- Write std::string surrounded by single quotes.
// Optional write without quotes.
Ostream& writeQuoted
(
const std::string&,
const bool quoted=true
);
//- Write label
Ostream& write(const label);
......
......@@ -152,8 +152,9 @@ Foam::Istream& Foam::ISstream::read(token& t)
return *this;
}
// Strings: enclosed by double quotes.
// Strings: enclosed by single or double quotes.
case token::BEGIN_STRING :
case token::BEGIN_QSTRING :
{
putback(c);
string* sPtr = new string;
......@@ -366,7 +367,13 @@ Foam::Istream& Foam::ISstream::read(string& str)
return *this;
}
if (c != token::BEGIN_STRING)
char endTok = token::END_STRING;
if (c == token::BEGIN_QSTRING)
{
endTok = token::END_QSTRING;
}
else if (c != token::BEGIN_STRING)
{
buf[0] = '\0';
......@@ -382,52 +389,49 @@ Foam::Istream& Foam::ISstream::read(string& str)
while (get(c))
{
switch (c)
if (c == endTok)
{
case token::END_STRING :
if (escaped)
{
escaped = false;
i--; // overwrite backslash
}
else
{
// done reading string
buf[i] = '\0';
str = buf;
return *this;
}
break;
case token::NL :
if (escaped)
{
escaped = false;
i--; // overwrite backslash
}
else
{
buf[i] = '\0';
buf[errLen] = '\0';
FatalIOErrorIn("ISstream::read(string&)", *this)
<< "found '\\n' while reading string \""
<< buf << "...\""
<< exit(FatalIOError);
return *this;
}
break;
case '\\':
escaped = !escaped; // toggle state (retains backslashes)
break;
default:
if (escaped)
{
escaped = false;
break;
i--; // overwrite backslash
}
else
{
// done reading string
buf[i] = '\0';
str = buf;
return *this;
}
}
else if (c == token::NL)
{
if (escaped)
{
escaped = false;
i--; // overwrite backslash
}
else
{
buf[i] = '\0';
buf[errLen] = '\0';
FatalIOErrorIn("ISstream::read(string&)", *this)
<< "found '\\n' while reading string \""
<< buf << "...\""
<< exit(FatalIOError);
return *this;
}
}
else if (c == '\\')
{
escaped = !escaped; // toggle state (retains backslashes)
}
else
{
escaped = false;
}
buf[i] = c;
if (i++ == maxLen)
......
......@@ -74,28 +74,26 @@ Foam::Ostream& Foam::OSstream::write(const string& str)
{
register char c = *iter;
switch (c)
if (c == '\\')
{
case '\\' :
backslash++;
// suppress output until we know if other characters follow
continue;
break;
case token::NL :
lineNumber_++;
backslash++; // backslash escape for newline
break;
case token::END_STRING :
backslash++; // backslash escape for double-quote
break;
backslash++;
// suppress output until we know if other characters follow
continue;
}
else if (c == token::NL)
{
lineNumber_++;
backslash++; // backslash escape for newline
}
else if (c == token::END_STRING)
{
backslash++; // backslash escape for quote
}
// output pending backslashes
while (backslash)
{
os_ << '\\'; // escape for new-line
os_ << '\\';
backslash--;
}
......@@ -103,7 +101,7 @@ Foam::Ostream& Foam::OSstream::write(const string& str)
}
// silently drop any trailing backslashes
// they would otherwise appear like an escaped double-quote
// they would otherwise appear like an escaped end-quote
os_ << token::END_STRING;
......@@ -112,6 +110,68 @@ Foam::Ostream& Foam::OSstream::write(const string& str)
}
Foam::Ostream& Foam::OSstream::writeQuoted
(
const std::string& str,
const bool quoted
)
{
if (quoted)
{
os_ << token::BEGIN_QSTRING;
register int backslash = 0;
for
(
string::const_iterator iter = str.begin();
iter != str.end();
++iter
)
{
register char c = *iter;
if (c == '\\')
{
backslash++;
// suppress output until we know if other characters follow
continue;
}
else if (c == token::NL)
{
lineNumber_++;
backslash++; // backslash escape for newline
}
else if (c == token::END_QSTRING)
{
backslash++; // backslash escape for quote
}
// output pending backslashes
while (backslash)
{
os_ << '\\';
backslash--;
}
os_ << c;
}
// silently drop any trailing backslashes
// they would otherwise appear like an escaped end-quote
os_ << token::END_QSTRING;
}
else
{
// output unquoted string, only advance line number on newline
lineNumber_ += string(str).count(token::NL);
os_ << str;
}
setState(os_.rdstate());
return *this;
}
Foam::Ostream& Foam::OSstream::write(const label val)
{
os_ << val;
......
......@@ -141,6 +141,14 @@ public:
// double-quote.
virtual Ostream& write(const string&);
//- Write std::string surrounded by single quotes.
// Optional write without quotes.
virtual Ostream& writeQuoted
(
const std::string&,
const bool quoted=true
);
//- Write label
virtual Ostream& write(const label);
......
......@@ -115,6 +115,17 @@ Foam::Ostream& Foam::prefixOSstream::write(const string& val)
}
Foam::Ostream& Foam::prefixOSstream::writeQuoted
(
const std::string& val,
const bool quoted
)
{
checkWritePrefix();
return OSstream::writeQuoted(val, quoted);
}
Foam::Ostream& Foam::prefixOSstream::write(const label val)
{
checkWritePrefix();
......
......@@ -114,6 +114,14 @@ public:
//- Write string
virtual Ostream& write(const string&);
//- Write std::string
// Specify if string should be single quoted or remain unquoted.
virtual Ostream& writeQuoted
(
const std::string&,
const bool quoted=true
);
//- Write label
virtual Ostream& write(const label);
......
......@@ -105,6 +105,7 @@ public:
// Access
//- Return the string
string str() const
{
return dynamic_cast<const std::istringstream&>(stream()).str();
......
......@@ -57,7 +57,7 @@ public:
// Constructors
//- Set stream status
//- Construct and set stream status
OStringStream
(
streamFormat format=ASCII,
......@@ -106,6 +106,7 @@ public:
// Access
//- Return the string
string str() const
{
return dynamic_cast<const std::ostringstream&>(stream()).str();
......
......@@ -92,28 +92,31 @@ public:
//- Standard punctuation tokens
enum punctuationToken
{
NULL_TOKEN = '\0',
SPACE = ' ',
TAB = '\t',
NL = '\n',
END_STATEMENT = ';',
BEGIN_LIST = '(',
END_LIST = ')',
BEGIN_SQR = '[',
END_SQR = ']',
BEGIN_BLOCK = '{',
END_BLOCK = '}',
COLON = ':',
COMMA = ',',
BEGIN_STRING = '"',
END_STRING = '"',
ASSIGN = '=',
ADD = '+',
SUBTRACT = '-',
MULTIPLY = '*',
DIVIDE = '/'
NULL_TOKEN = '\0',
SPACE = ' ',
TAB = '\t',
NL = '\n',
END_STATEMENT = ';',
BEGIN_LIST = '(',
END_LIST = ')',
BEGIN_SQR = '[',
END_SQR = ']',
BEGIN_BLOCK = '{',
END_BLOCK = '}',
COLON = ':',
COMMA = ',',
BEGIN_STRING = '"',
END_STRING = BEGIN_STRING,
BEGIN_QSTRING = '\'',
END_QSTRING = BEGIN_QSTRING,
ASSIGN = '=',
ADD = '+',
SUBTRACT = '-',
MULTIPLY = '*',
DIVIDE = '/'
};
......
......@@ -94,7 +94,12 @@ inline Foam::fileName::fileName(const char* str)
inline bool Foam::fileName::valid(char c)
{
return (!isspace(c) && c != '"');
return
(
!isspace(c)
&& c != '"' // string quote
&& c != '\'' // string quote
);
}
......
......@@ -119,12 +119,13 @@ inline bool Foam::word::valid(char c)
{
return
(
!isspace(c)
&& c != '"'
&& c != '/'
&& c != ';'
&& c != '{'
&& c != '}'
!isspace(c)
&& c != '"' // string quote
&& c != '\'' // string quote
&& c != '/' // path separator
&& c != ';' // end statement
&& c != '{' // beg subdict
&& c != '}' // end subdict
);
}
......
......@@ -91,7 +91,7 @@ public:
// Note that 'REGEXP' is implicit if 'NOCASE' is specified alone.
enum compOption
{
LITERAL = 0, /*!< treat as a strign literal */
LITERAL = 0, /*!< treat as a string literal */
DETECT = 1, /*!< treat as regular expression */
REGEXP = 2, /*!< detect if the string contains meta-characters */
NOCASE = 4, /*!< ignore case in regular expression */
......
......@@ -78,14 +78,7 @@ Foam::Istream& Foam::operator>>(Istream& is, wordRe& w)
Foam::Ostream& Foam::operator<<(Ostream& os, const wordRe& w)
{
if (w.isPattern())
{
os.write(static_cast<const string&>(w));
}
else
{
os.write(static_cast<const word&>(w));
}
os.writeQuoted(w, w.isPattern());
os.check("Ostream& operator<<(Ostream&, const wordRe&)");
return os;
}
......@@ -99,7 +92,7 @@ Foam::Ostream& Foam::wordRe::info(Ostream& os) const
}
else
{
os << "wordRe(plain) '" << *this << "'";
os << "wordRe(plain) \"" << *this << '"';
}
os.flush();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment