13 Commits

Author SHA1 Message Date
Andrew Johnson b724b72624 Clear development flag for 4.7.0 release 2019-11-01 12:20:59 -05:00
Andrew Johnson fc42cf798e Release notes for 4.7.0 2019-11-01 11:09:28 -05:00
Marty Kraimer 71181afc93 Update .travis.yml 2019-09-13 09:15:35 -04:00
Ralph Lange b92a3ddaa4 rtd-ci: add read-the-docs integration 2019-09-06 14:18:19 +02:00
Andrew Johnson 246cceae3e Update version number to 4.7.0 DEVELOPMENT 2019-08-13 10:46:37 -05:00
mrkraimer 3f4df39ee0 fix issue #62 PvaClientData::parse bug 2019-08-12 06:03:55 -04:00
Marty Kraimer 837924af2e Update RELEASE_NOTES.md 2019-08-02 08:45:10 -04:00
Marty Kraimer 7b0e2b5986 Merge pull request #61 from mrkraimer/master
add JSON support
2019-08-02 08:42:29 -04:00
mrkraimer c84b24bb30 Merge https://github.com/epics-base/pvaClientCPP
merge to get latest hanges from epics-base
2019-08-02 05:44:42 -04:00
mrkraimer f58c5159fc add streamJSON 2019-07-19 09:49:40 -04:00
mrkraimer a91ba8ef9e fixed a bug 2019-07-17 10:43:13 -04:00
mrkraimer ddb36536fe add zeroArrayLength 2019-07-16 10:33:39 -04:00
mrkraimer 9153036ccc added JSON support 2019-07-16 09:42:08 -04:00
11 changed files with 326 additions and 9 deletions
+17
View File
@@ -0,0 +1,17 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Build documentation in the documentation/ directory with Sphinx
sphinx:
configuration: documentation/conf.py
# Build documentation with MkDocs
#mkdocs:
# configuration: mkdocs.yml
# Optionally build your docs in additional formats such as PDF and ePub
formats: all
-1
View File
@@ -28,4 +28,3 @@ env:
- BRBASE=7.0 RTEMS=4.9 TEST=NO
- BRBASE=3.16
- BRBASE=3.15
- BRBASE=3.14
+7 -6
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = pvaClientCPP
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER = 4.7.0
# 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
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
STRIP_FROM_PATH = src
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@@ -161,7 +161,7 @@ STRIP_FROM_PATH =
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
STRIP_FROM_INC_PATH = src
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@@ -765,7 +765,8 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = include
INPUT = src \
src/pv
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -796,7 +797,7 @@ FILE_PATTERNS =
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
RECURSIVE = NO
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
@@ -1035,7 +1036,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = documentation/html
HTML_OUTPUT = html/doxygen
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
+10 -1
View File
@@ -1,3 +1,12 @@
# Version number for the PVA Client API and shared library
EPICS_PVACLIENT_MAJOR_VERSION = 4
EPICS_PVACLIENT_MINOR_VERSION = 6
EPICS_PVACLIENT_MINOR_VERSION = 7
EPICS_PVACLIENT_MAINTENANCE_VERSION = 0
# Development flag, set to zero for release versions
EPICS_PVACLIENT_DEVELOPMENT_FLAG = 0
# Immediately after a release the MAINTENANCE_VERSION
# will be incremented and the DEVELOPMENT_FLAG set to 1
+8
View File
@@ -2,6 +2,14 @@
This document summarizes the changes to the module between releases.
## Release 4.7.0 (EPICS 7.0.3.1, Nov 2019)
* added JSON support for put and putGet
* Fix for
[GitHub issue #62](https://github.com/epics-base/pvaClientCPP/issues/62)
* Doxygen updates and read-the-docs integration.
## Release 4.6.0 (EPICS 7.0.3, Jul 2019)
* pvaClient now handles exceptions from the server properly (issue #54).
+7
View File
@@ -0,0 +1,7 @@
.wy-side-nav-search {
background-color: #18334B;
}
.wy-side-nav-search input[type="text"] {
border-color: #18334b;
}
+80
View File
@@ -0,0 +1,80 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'normativeTypes (C++)'
copyright = '2019, EPICS Controls.'
author = 'EPICS'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.intersphinx',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# Intersphinx links to subprojects
intersphinx_mapping = {
}
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_css_files = [
'css/custom.css',
]
master_doc = 'index'
html_theme_options = {
'logo_only': True,
}
html_logo = "images/EPICS_white_logo_v02.png"
html_extra_path = [
'../html',
'pvaClientCPP.html',
]
# -- Run Doxygen ------------------------------------------------------------
import subprocess
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

+17
View File
@@ -0,0 +1,17 @@
pvaClient (C++) Library
========================
.. toctree::
:hidden:
EPICS Website <https://epics-controls.org>
EPICS Documentation Home <https://docs.epics-controls.org>
.. toctree::
:maxdepth: 1
:caption: pvaClientCPP
Reference Manual <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/pvaClientCPP.html>
API Documentation <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/doxygen>
Source Code Repository on GitHub <https://github.com/epics-base/pvaClientCPP>
+33 -1
View File
@@ -17,6 +17,7 @@
#include <list>
#include <iostream>
#include <ostream>
#include <sstream>
#include <pv/requester.h>
#include <pv/status.h>
@@ -613,6 +614,7 @@ public:
void setData(
epics::pvData::PVStructurePtr const & pvStructureFrom,
epics::pvData::BitSetPtr const & bitSetFrom);
/** @brief Is there a top level field named value.
* @return The answer.
*/
@@ -679,6 +681,29 @@ public:
* @return The timeStamp.
*/
epics::pvData::TimeStamp getTimeStamp();
/** @brief parse from args
*
* Accepts arguments of the form json or field='value' where value is json syntax.
* field is name.name...
* @param args The arguments
* @throw runtime_error if failure.
*/
void parse(const std::vector<std::string> &args);
/** @brief generate JSON output from the current PVStructure
*
* @param strm output stream
* @param ignoreUnprintable false or true; default is true.
* @param multiline false or true; default is false
*
* @throw runtime_error if failure.
*/
void streamJSON(
std::ostream& strm,
bool ignoreUnprintable = true,
bool multiLine = false);
/** @brief set length of all array fields to 0
*/
void zeroArrayLength();
/** @brief Factory method for creating an instance of PvaClientData.
*
* NOTE: Not normally called by clients
@@ -691,12 +716,19 @@ protected:
void checkValue();
std::string messagePrefix;
private:
void parse(
const std::string &arg,
const epics::pvData::PVFieldPtr &dest,
epics::pvData::BitSetPtr &bitSet);
void parse(
const std::string &arg,
const epics::pvData::PVUnionPtr &dest);
void zeroArrayLength(const epics::pvData::PVStructurePtr &pvStructure);
epics::pvData::StructureConstPtr structure;
epics::pvData::PVStructurePtr pvStructure;
epics::pvData::BitSetPtr bitSet;
epics::pvData::PVFieldPtr pvValue;
epics::pvData::PVAlarm pvAlarm;
epics::pvData::PVTimeStamp pvTimeStamp;
+147
View File
@@ -11,9 +11,17 @@
#include <typeinfo>
#include <sstream>
#include <istream>
#include <ostream>
#include <pv/createRequest.h>
#include <pv/convert.h>
#include <pv/pvEnumerated.h>
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
# include <pv/json.h>
# define USE_JSON
#endif
#define epicsExportSharedSymbols
@@ -106,6 +114,7 @@ void PvaClientData::setData(
pvValue = pvStructure->getSubField("value");
}
bool PvaClientData::hasValue()
{
if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n";
@@ -358,4 +367,142 @@ TimeStamp PvaClientData::getTimeStamp()
throw std::runtime_error(messagePrefix + noTimeStamp);
}
void PvaClientData::zeroArrayLength()
{
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
zeroArrayLength(pvStructure);
}
void PvaClientData::parse(
const std::string &arg,const PVFieldPtr &dest,BitSetPtr & bitSet)
{
#ifdef USE_JSON
std::istringstream strm(arg);
parseJSON(strm, dest,&(*bitSet));
#else
throw std::runtime_error("JSON support not built");
#endif
}
void PvaClientData::parse(
const std::string &arg,const PVUnionPtr &pvUnion)
{
if(pvUnion->getUnion()->isVariant()) {
throw std::runtime_error(messagePrefix + "varient union not implemented");
}
size_t iequals = arg.find_first_of('=');
string field;
string rest;
if(iequals==std::string::npos) {
string mess(arg);
mess += " was expected to start with field=";
throw std::runtime_error(messagePrefix + mess);
}
field = arg.substr(0,iequals);
rest = arg.substr(iequals+1);
PVFieldPtr pvField(pvUnion->select(field));
if(pvField->getField()->getType()==epics::pvData::union_) {
PVUnionPtr pvu = static_pointer_cast<PVUnion>(pvField);
parse(rest,pvu);
return;
}
BitSetPtr bs;
parse(rest,pvField,bs);
return;
}
void PvaClientData::parse(const std::vector<std::string> &args)
{
if(!pvStructure) throw std::runtime_error(messagePrefix + noStructure);
if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
size_t num = args.size();
if(num<1) throw std::runtime_error(messagePrefix + " no arguments");
for(size_t i=0; i<num; ++i)
{
string val = args[i];
size_t iequals = val.find_first_of('=');
string field;
string rest(val);
if(iequals==std::string::npos) {
parse(rest,pvStructure,bitSet);
continue;
}
field = val.substr(0,iequals);
rest = val.substr(iequals+1);
if(field.size()==std::string::npos) {
parse(rest,pvStructure,bitSet);
continue;
}
PVFieldPtr pvField(pvStructure->getSubField(field));
if(!pvField) throw std::runtime_error(messagePrefix + field +" does not exist");
// look for enumerated structure
PVEnumerated pvEnumerated;
bool result = pvEnumerated.attach(pvField);
if(result) {
PVStringArray::const_svector choices(pvEnumerated.getChoices());
for(size_t i=0; i<choices.size(); ++i) {
if(choices[i]==rest) {
pvEnumerated.setIndex(i);
return;
}
}
}
// look for union
PVUnionPtr pvUnion(pvStructure->getSubField<PVUnion>(field));
if(pvUnion) {
parse(rest,pvUnion);
bitSet->set(pvUnion->getFieldOffset());
return;
}
parse(rest,pvField,bitSet);
}
}
void PvaClientData::streamJSON(
std::ostream& strm,
bool ignoreUnprintable,
bool multiLine)
{
#ifdef USE_JSON
JSONPrintOptions opts;
opts.ignoreUnprintable = ignoreUnprintable;
opts.multiLine = multiLine;
printJSON(strm,*pvStructure,*bitSet,opts);
#else
throw std::runtime_error("JSON support not built");
#endif
}
void PvaClientData::zeroArrayLength(const epics::pvData::PVStructurePtr &pvStructure)
{
const PVFieldPtrArray pvFields(pvStructure->getPVFields());
for(size_t i=0; i<pvFields.size(); ++i) {
PVFieldPtr pvField = pvFields[i];
Type type(pvField->getField()->getType());
switch(type) {
case epics::pvData::scalarArray:
{
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
pvScalarArray->setLength(0);
}
break;
case epics::pvData::structureArray:
{
PVStructureArrayPtr pvStructureArray = static_pointer_cast<PVStructureArray>(pvField);
pvStructureArray->setLength(0);
}
break;
case epics::pvData::structure:
{
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
zeroArrayLength(pvStructure);
}
break;
default:
break;
}
}
}
}}