7 Commits
8.0.2 ... 8.0.3

Author SHA1 Message Date
Michael Davidsaver
b2b42d5f8c Update version numbers for release 2020-07-26 13:29:52 -07:00
Michael Davidsaver
90b1f2f6da doc 2020-06-17 14:08:14 -07:00
Michael Davidsaver
2e775ef2fb drop THROW_BASE_EXCEPTION_CAUSE() 2020-06-17 14:08:14 -07:00
Michael Davidsaver
f17d2bbca1 add maybeQuote()
Something for the *NIX gurus
to light their pipes with.
2020-06-17 14:08:14 -07:00
Michael Davidsaver
79b02254c4 update ci-scripts to 3.0.1 2020-06-17 14:06:50 -07:00
Michael Davidsaver
19245ce805 sharedVector extend base_ptr() to VS2013 2020-06-03 10:14:38 -07:00
Andrew Johnson
0fa927afa7 Set next development version 2020-05-28 16:26:00 -05:00
14 changed files with 98 additions and 84 deletions

View File

@@ -1,8 +1,6 @@
# .appveyor.yml for use with EPICS Base ci-scripts
# (see: https://github.com/epics-base/ci-scripts)
# This is YAML - indentation levels are crucial
cache:
- C:\Users\appveyor\.tools
@@ -41,14 +39,14 @@ configuration:
# Environment variables: compiler toolchain, base version, setup file, ...
environment:
# common / default variables for all jobs
SETUP_PATH: .ci-local:.ci
SETUP_PATH: .ci-local
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
CMP: vs2019
BASE: 7.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
CMP: mingw
CMP: gcc
BASE: 7.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMP: vs2017
@@ -66,15 +64,15 @@ platform:
#---------------------------------#
build_script:
- cmd: python .ci/appveyor/do.py prepare
- cmd: python .ci/appveyor/do.py build
- cmd: python .ci/cue.py prepare
- cmd: python .ci/cue.py build
test_script:
- cmd: python .ci/appveyor/do.py test
- cmd: python .ci/cue.py test
on_finish:
- ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
- cmd: python .ci/appveyor/do.py build test-results -s
- cmd: python .ci/cue.py build test-results -s
#---------------------------------#
# debugging #
@@ -93,10 +91,4 @@ on_finish:
#---------------------------------#
notifications:
- provider: Email
to:
- me@example.com
on_build_success: false
- provider: GitHubPullRequest

2
.ci

Submodule .ci updated: ecb7e43660...12d769835e

View File

@@ -1,8 +1,6 @@
# .travis.yml for use with EPICS Base ci-scripts
# (see: https://github.com/epics-base/ci-scripts)
# This is YAML - indentation levels are crucial
language: cpp
compiler: gcc
dist: bionic
@@ -13,7 +11,7 @@ cache:
env:
global:
- SETUP_PATH=.ci-local:.ci
- SETUP_PATH=.ci-local
addons:
apt:
@@ -31,34 +29,24 @@ addons:
- qemu-system-x86
install:
- ./.ci/travis/prepare.sh
- python .ci/cue.py prepare
script:
- ./.ci/travis/build.sh
# If you need to do more during install and build,
# add a local directory to your module and do e.g.
# - ./.ci-local/travis/install-extras.sh
# Define build jobs
# Well-known variables to use
# SET source setup file
# EXTRA content will be added to make command line
# STATIC set to YES for static build (default: NO)
# TEST set to NO to skip running the tests (default: YES)
# VV set to make build scripts verbose (default: unset)
# Usually from setup files, but may be specified or overridden
# on a job line
# MODULES list of dependency modules
# BASE branch or release tag name of the EPICS Base to use
# <MODULE> branch or release tag for a specific module
# ... see README for setup file syntax description
- python .ci/cue.py build
- python .ci/cue.py test-results
jobs:
include:
# Windows builds
- env: BASE=7.0
os: windows
compiler: vs2017
- env: BASE=7.0
os: windows
# Different configurations of default gcc and clang
- env: BASE=7.0
@@ -84,11 +72,9 @@ jobs:
# Cross-compilations to Windows using MinGW and WINE
- env: BASE=7.0 WINE=32 TEST=NO STATIC=YES
compiler: mingw
- env: BASE=7.0 WINE=32 TEST=NO BCFG=static
- env: BASE=7.0 WINE=64 TEST=NO STATIC=NO
compiler: mingw
- env: BASE=7.0 WINE=64 TEST=NO
# Other gcc versions (added as an extra package)

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = "PVData C++"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 8.0.2
PROJECT_NUMBER = 8.0.3
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@@ -2,7 +2,7 @@
EPICS_PVD_MAJOR_VERSION = 8
EPICS_PVD_MINOR_VERSION = 0
EPICS_PVD_MAINTENANCE_VERSION = 2
EPICS_PVD_MAINTENANCE_VERSION = 3
# Development flag, set to zero for release versions

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = "PVData C++"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 8.0.2
PROJECT_NUMBER = 8.0.3
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@@ -2,6 +2,15 @@
@page release_notes Release Notes
Release 8.0.3 (July 2020)
=========================
- Incompatible changes
- Removed THROW_BASE_EXCEPTION_CAUSE() macro which has long ignored its cause.
Any external users should switch to the functionally identical THROW_BASE_EXCEPTION_CAUSE()
- Various printing of functions now conditionally escape strings
including quote '\"' and similar charactors.
Release 8.0.2 (May 2020)
========================

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

@@ -229,7 +229,6 @@ private:
#endif
#define THROW_BASE_EXCEPTION(msg) THROW_EXCEPTION2(::epics::pvData::BaseException, msg)
#define THROW_BASE_EXCEPTION_CAUSE(msg, cause) THROW_EXCEPTION2(::epics::pvData::BaseException, msg)
}
}

View File

@@ -544,11 +544,11 @@ private:
/* Hack alert.
* For reasons of simplicity and efficiency, we want to use raw pointers for iteration.
* However, shared_ptr::get() isn't defined when !m_sdata, although practically it gives NULL.
* Unfortunately, many of the MSVC (<= VS 2010) STL methods assert() that iterators are never NULL.
* Unfortunately, many of the MSVC (<= VS 2013) STL methods assert() that iterators are never NULL.
* So we fudge here by abusing 'this' so that our iterators are always !NULL.
*/
inline E* base_ptr() const {
#if defined(_MSC_VER) && _MSC_VER<=1600
#if defined(_MSC_VER) && _MSC_VER<=1800
return this->m_count ? this->m_sdata.get() : (E*)(this-1);
#else
return this->m_sdata.get();

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

@@ -31,16 +31,6 @@ void Unroller::unroll<0>(double /*d*/) {
THROW_BASE_EXCEPTION("the root cause");
}
void internalTestBaseException(int /*unused*/ = 0)
{
try {
// NOTE: 5, 4, 3, 2, 1 calls will be optimized and not shown
Unroller().unroll<5>(42.0);
} catch (BaseException& be3) {
THROW_BASE_EXCEPTION_CAUSE("exception 1", be3);
}
}
void testBaseExceptionTest() {
printf("testBaseException... ");
@@ -50,16 +40,6 @@ void testBaseExceptionTest() {
printf("\n\n%s\n\n", be.what());
}
try {
try {
internalTestBaseException();
} catch (BaseException& be2) {
THROW_BASE_EXCEPTION_CAUSE("exception 2", be2);
}
} catch (BaseException& be) {
printf("\n\n%s\n\n", be.what());
}
testPass("testBaseException");
}

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();