add maybeQuote()

Something for the *NIX gurus
to light their pipes with.
This commit is contained in:
Michael Davidsaver
2020-06-16 16:21:59 -07:00
parent 79b02254c4
commit f17d2bbca1
4 changed files with 62 additions and 14 deletions

View File

@@ -144,8 +144,7 @@ PVString::PVString(ScalarConstPtr const & scalar)
std::ostream& PVString::dumpValue(std::ostream& o) const
{
// we escape, but do not quote, for scalar string
o<<escape(get());
o<<maybeQuote(get());
return o;
}
@@ -233,7 +232,7 @@ std::ostream& PVValueArray<T>::dumpValue(std::ostream& o) const
template<>
std::ostream& PVValueArray<std::string>::dumpValue(std::ostream& o, size_t index) const
{
return o << '"' << escape(this->view().at(index)) << '"';
return o << maybeQuote(this->view().at(index));
}
template<>
@@ -244,9 +243,9 @@ std::ostream& PVValueArray<std::string>::dumpValue(std::ostream& o) const
end(v.end());
o << '[';
if(it!=end) {
o << '"' << escape(*it++) << '"';
o << maybeQuote(*it++);
for(; it!=end; ++it)
o << ", \"" << escape(*it) << '"';
o << ", " << maybeQuote(*it);
}
return o << ']';

View File

@@ -171,7 +171,7 @@ bool printEnumT(std::ostream& strm, const PVStructure& top, bool fromtop)
if(I>=ch.size()) {
strm<<" <undefined>";
} else {
strm<<' '<<escape(ch[I]);
strm<<' '<<maybeQuote(ch[I]);
}
return true;
}
@@ -180,7 +180,7 @@ void csvEscape(std::string& S)
{
// concise, not particularly efficient...
std::string temp(escape(S).style(escape::CSV).str());
if(S.find_first_of(" ,\\")!=S.npos) {// only quote if necessary (stupid Excel)
if(S.find_first_of("\" ,\\")!=S.npos) {// only quote if necessary (stupid Excel)
std::string temp2;
temp2.reserve(temp.size()+2);
temp2.push_back('\"');
@@ -188,7 +188,7 @@ void csvEscape(std::string& S)
temp2.push_back('\"');
temp2.swap(temp);
}
S = temp;
S.swap(temp);
}
bool printTable(std::ostream& strm, const PVStructure& top)
@@ -514,4 +514,38 @@ std::ostream& operator<<(std::ostream& strm, const escape& Q)
return strm;
}
std::ostream& operator<<(std::ostream& strm, const maybeQuote& q)
{
bool esc = false;
for(size_t i=0, N=q.s.size(); i<N && !esc; i++) {
switch(q.s[i]) {
case '\a':
case '\b':
case '\f':
case '\n':
case '\r':
case '\t':
case ' ':
case '\v':
case '\\':
case '\'':
case '\"':
esc = true;
break;
default:
if(!isprint(q.s[i])) {
esc = true;
}
break;
}
}
if(esc) {
strm<<'"'<<escape(q.s)<<'"';
} else {
strm<<q.s;
}
return strm;
}
}} //epics::pvData

View File

@@ -237,6 +237,14 @@ public:
std::ostream& operator<<(std::ostream& strm, const escape& Q);
};
struct maybeQuote {
const std::string& s;
maybeQuote(const std::string& s) :s(s) {}
};
epicsShareExtern
std::ostream& operator<<(std::ostream& strm, const maybeQuote& q);
}} // end namespace
#endif // PVTYPECAST_H

View File

@@ -197,12 +197,12 @@ void showNTEnum()
input->getSubFieldT<pvd::PVInt>("value.index")->put(1);
testDiff("<undefined> (1) a two\n", print(input->stream()), "two");
testDiff("<undefined> (1) \"a two\"\n", print(input->stream()), "two");
testDiff("epics:nt/NTEnum:1.0 \n"
" enum_t value (1) a two\n"
" enum_t value (1) \"a two\"\n"
" int index 1\n"
" string[] choices [\"one\", \"a two\"]\n"
" string[] choices [one, \"a two\"]\n"
" alarm_t alarm \n"
" int severity 0\n"
" int status 0\n"
@@ -299,7 +299,7 @@ void testRaw()
testDiff("omg \n"
" string scalar \n" // bit 1
" string[] scalarArray [\"hello\", \"world\\x7F\"]\n"
" string[] scalarArray [hello, \"world\\x7F\"]\n"
" structure below\n"
" int A 0\n" // bit 4
" union select\n"
@@ -319,7 +319,7 @@ void testRaw()
testDiff("omg \n"
"\033[1m string scalar \n"
"\033[0m\033[1m string[] scalarArray [\"hello\", \"world\\x7F\"]\n"
"\033[0m\033[1m string[] scalarArray [hello, \"world\\x7F\"]\n"
"\033[0m structure below\n"
"\033[1m int A 0\n"
"\033[0m union select\n"
@@ -347,13 +347,20 @@ void testEscape()
testEqual("hello\"\"world", std::string(SB()<<pvd::escape("hello\"world").style(pvd::escape::CSV)));
testEqual("hello\"\"world", pvd::escape("hello\"world").style(pvd::escape::CSV).str());
testEqual("hello_world", std::string(SB()<<pvd::maybeQuote("hello_world")));
testEqual("\"hello_world\\\"\"", std::string(SB()<<pvd::maybeQuote("hello_world\"")));
testEqual("\"hello world\"", std::string(SB()<<pvd::maybeQuote("hello world")));
testEqual("\"hello\\nworld\"", std::string(SB()<<pvd::maybeQuote("hello\nworld")));
testEqual("\"hello\\\"world\"", std::string(SB()<<pvd::maybeQuote("hello\"world")));
testEqual("\"hello\\x7Fworld\"", std::string(SB()<<pvd::maybeQuote("hello\x7Fworld")));
}
} // namespace
MAIN(testprinter)
{
testPlan(20);
testPlan(26);
showNTScalarNumeric();
showNTScalarString();
showNTEnum();