Compare commits
86 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f66492ce4b | ||
|
|
e069c699e9 | ||
|
|
8963b2dba1 | ||
|
|
9ec9a526f5 | ||
|
|
b4114589ff | ||
| 6689c9ce1f | |||
|
|
0c1773f25d | ||
|
|
d0ff9a9592 | ||
|
|
bf36070860 | ||
|
|
5552773e5e | ||
|
|
b3a1077270 | ||
|
|
1c5f75bcd6 | ||
|
|
2455039594 | ||
|
|
f47676c225 | ||
|
|
0881e0ed86 | ||
|
|
e457b60b30 | ||
|
|
a6746f8161 | ||
|
|
144f0228cc | ||
|
|
7300e6b0bd | ||
|
|
0ef8a36172 | ||
|
|
c0be043aaf | ||
|
|
dd74289eaf | ||
|
|
3da69257a0 | ||
|
|
13e4e577bb | ||
|
|
5387face45 | ||
|
|
eac2a8e70f | ||
|
|
04fcb7e38f | ||
|
|
45018a2163 | ||
|
|
b7ad4478a4 | ||
|
|
c16f19c80e | ||
|
|
87018882d1 | ||
| 2547514abb | |||
|
|
9447eacbd2 | ||
|
|
0b424a71ec | ||
|
|
45671faaea | ||
|
|
016d1154fc | ||
|
|
f3911d5831 | ||
|
|
93e90c5a04 | ||
|
|
8039c75b3e | ||
|
|
a647c8b174 | ||
|
|
d3b4976ea2 | ||
|
|
b1c8303870 | ||
|
|
a3ef984f4f | ||
|
|
ca86a63180 | ||
|
|
07b79693af | ||
|
|
4ef9e18ac6 | ||
|
|
320cc3c60b | ||
|
|
45d0d76a7f | ||
|
|
b2b42d5f8c | ||
|
|
90b1f2f6da | ||
|
|
2e775ef2fb | ||
|
|
f17d2bbca1 | ||
|
|
79b02254c4 | ||
|
|
19245ce805 | ||
|
|
0fa927afa7 | ||
|
|
d9b3f98e35 | ||
|
|
81e7968230 | ||
|
|
06f3b96992 | ||
| 1038182a16 | |||
| 60091bfe56 | |||
| f4de6dd9b1 | |||
|
|
3d93a80cce | ||
|
|
94eff54fa9 | ||
|
|
e9dde4d2f8 | ||
|
|
0a5e22e5b0 | ||
|
|
3a5cfba4e1 | ||
|
|
07b75e4543 | ||
|
|
e4f150b34f | ||
|
|
ca2ae0d0e7 | ||
|
|
828506720c | ||
|
|
ad712b63f9 | ||
|
|
4c3d5a788d | ||
|
|
df89135455 | ||
|
|
95d452870c | ||
|
|
8a82ff9fe4 | ||
|
|
dd24b2ad75 | ||
|
|
17fa7a7724 | ||
|
|
d01ba94ed7 | ||
|
|
c7c7585950 | ||
|
|
f869936cfd | ||
|
|
0ad253c6f0 | ||
|
|
52d04d5044 | ||
|
|
bff2dc9cd2 | ||
|
|
b903df5d0d | ||
|
|
416d910577 | ||
|
|
37b7a0708f |
113
.appveyor.yml
Normal file
113
.appveyor.yml
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# .appveyor.yml for use with EPICS Base ci-scripts
|
||||||
|
# (see: https://github.com/epics-base/ci-scripts)
|
||||||
|
|
||||||
|
# This is YAML - indentation levels are crucial
|
||||||
|
|
||||||
|
#---------------------------------#
|
||||||
|
# build cache #
|
||||||
|
#---------------------------------#
|
||||||
|
# The AppVeyor cache allowance is way too small (1GB per account across all
|
||||||
|
# projects, branches and jobs) to be used for the dependency builds.
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- C:\Users\appveyor\.tools
|
||||||
|
|
||||||
|
#---------------------------------#
|
||||||
|
# repository cloning #
|
||||||
|
#---------------------------------#
|
||||||
|
|
||||||
|
init:
|
||||||
|
# Set autocrlf to make batch files work
|
||||||
|
- cmd: git config --global core.autocrlf true
|
||||||
|
|
||||||
|
clone_depth: 5
|
||||||
|
|
||||||
|
#---------------------------------#
|
||||||
|
# build matrix configuration #
|
||||||
|
#---------------------------------#
|
||||||
|
|
||||||
|
# Build Configurations: dll/static, regular/debug
|
||||||
|
configuration:
|
||||||
|
- dynamic
|
||||||
|
- static
|
||||||
|
- dynamic-debug
|
||||||
|
- static-debug
|
||||||
|
|
||||||
|
# Environment variables: compiler toolchain, base version, setup file, ...
|
||||||
|
environment:
|
||||||
|
# common / default variables for all jobs
|
||||||
|
SETUP_PATH: .ci-local
|
||||||
|
EPICS_TEST_IMPRECISE_TIMING: YES
|
||||||
|
BASE: 7.0
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
- CMP: vs2019
|
||||||
|
BASE: 3.15
|
||||||
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
- CMP: vs2019
|
||||||
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
- CMP: vs2017
|
||||||
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
|
- CMP: vs2015
|
||||||
|
- CMP: gcc
|
||||||
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
# TODO: static linking w/ readline isn't working. Bypass auto-detect
|
||||||
|
COMMANDLINE_LIBRARY: EPICS
|
||||||
|
|
||||||
|
# Platform: processor architecture
|
||||||
|
platform: x64
|
||||||
|
|
||||||
|
# Matrix configuration: exclude sets of jobs
|
||||||
|
matrix:
|
||||||
|
exclude:
|
||||||
|
# MinGW debug builds use the same libraries, unlike VS
|
||||||
|
- configuration: dynamic-debug
|
||||||
|
CMP: gcc
|
||||||
|
- configuration: static-debug
|
||||||
|
CMP: gcc
|
||||||
|
|
||||||
|
#---------------------------------#
|
||||||
|
# building & testing #
|
||||||
|
#---------------------------------#
|
||||||
|
|
||||||
|
install:
|
||||||
|
- cmd: git submodule update --init --recursive
|
||||||
|
- cmd: pip install git+https://github.com/mdavidsaver/ci-core-dumper#egg=ci-core-dumper
|
||||||
|
- cmd: python .ci/cue.py prepare
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- cmd: python .ci/cue.py build
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- cmd: python -m ci_core_dumper install
|
||||||
|
- cmd: python .ci/cue.py -T 20M test
|
||||||
|
|
||||||
|
on_finish:
|
||||||
|
- ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||||
|
- cmd: python .ci/cue.py -T 5M test-results
|
||||||
|
|
||||||
|
on_failure:
|
||||||
|
- cmd: python -m ci_core_dumper report
|
||||||
|
|
||||||
|
#---------------------------------#
|
||||||
|
# debugging #
|
||||||
|
#---------------------------------#
|
||||||
|
|
||||||
|
## To connect by remote desktop to a failed build, uncomment the lines below.
|
||||||
|
## You must connect within the usual build timeout limit (60 minutes),
|
||||||
|
## so adjust the build matrix above to just build the config of interest.
|
||||||
|
|
||||||
|
#on_failure:
|
||||||
|
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||||
|
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||||
|
|
||||||
|
#---------------------------------#
|
||||||
|
# notifications #
|
||||||
|
#---------------------------------#
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
- provider: Email
|
||||||
|
to:
|
||||||
|
- core-talk@aps.anl.gov
|
||||||
|
on_build_success: false
|
||||||
|
- provider: GitHubPullRequest
|
||||||
1
.ci
Submodule
1
.ci
Submodule
Submodule .ci added at 20f8e05393
6
.ci-local/defaults.set
Normal file
6
.ci-local/defaults.set
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# EPICS Base
|
||||||
|
BASE_DIRNAME=base
|
||||||
|
BASE_REPONAME=epics-base
|
||||||
|
BASE_REPOOWNER=epics-base
|
||||||
|
BASE_VARNAME=EPICS_BASE
|
||||||
|
BASE_RECURSIVE=NO
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e -x
|
|
||||||
|
|
||||||
make -j2
|
|
||||||
|
|
||||||
if [ "$TEST" != "NO" ]
|
|
||||||
then
|
|
||||||
make -j2 tapfiles
|
|
||||||
make -j2 -s test-results
|
|
||||||
fi
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e -x
|
|
||||||
|
|
||||||
cat << EOF > configure/RELEASE.local
|
|
||||||
EPICS_BASE=$HOME/.source/epics-base
|
|
||||||
EOF
|
|
||||||
|
|
||||||
install -d "$HOME/.source"
|
|
||||||
cd "$HOME/.source"
|
|
||||||
|
|
||||||
git clone --quiet --depth 5 --branch "$BRBASE" https://github.com/${REPOBASE:-epics-base}/epics-base.git epics-base
|
|
||||||
(cd epics-base && git log -n1 )
|
|
||||||
|
|
||||||
EPICS_HOST_ARCH=`sh epics-base/startup/EpicsHostArch`
|
|
||||||
|
|
||||||
# requires wine and g++-mingw-w64-i686
|
|
||||||
if [ "$WINE" = "32" ]
|
|
||||||
then
|
|
||||||
echo "Cross mingw32"
|
|
||||||
sed -i -e '/CMPLR_PREFIX/d' epics-base/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
|
|
||||||
cat << EOF >> epics-base/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
|
|
||||||
CMPLR_PREFIX=i686-w64-mingw32-
|
|
||||||
EOF
|
|
||||||
cat << EOF >> epics-base/configure/CONFIG_SITE
|
|
||||||
CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$STATIC" = "YES" ]
|
|
||||||
then
|
|
||||||
echo "Build static libraries/executables"
|
|
||||||
cat << EOF >> epics-base/configure/CONFIG_SITE
|
|
||||||
SHARED_LIBRARIES=NO
|
|
||||||
STATIC_BUILD=YES
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$CMPLR" in
|
|
||||||
clang)
|
|
||||||
echo "Host compiler is clang"
|
|
||||||
cat << EOF >> epics-base/configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH
|
|
||||||
GNU = NO
|
|
||||||
CMPLR_CLASS = clang
|
|
||||||
CC = clang
|
|
||||||
CCC = clang++
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# hack
|
|
||||||
sed -i -e 's/CMPLR_CLASS = gcc/CMPLR_CLASS = clang/' epics-base/configure/CONFIG.gnuCommon
|
|
||||||
|
|
||||||
clang --version
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Host compiler is default"
|
|
||||||
gcc --version
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
cat <<EOF >> epics-base/configure/CONFIG_SITE
|
|
||||||
USR_CPPFLAGS += $USR_CPPFLAGS
|
|
||||||
USR_CFLAGS += $USR_CFLAGS
|
|
||||||
USR_CXXFLAGS += $USR_CXXFLAGS
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# set RTEMS to eg. "4.9" or "4.10"
|
|
||||||
# requires qemu, bison, flex, texinfo, install-info
|
|
||||||
if [ -n "$RTEMS" ]
|
|
||||||
then
|
|
||||||
echo "Cross RTEMS${RTEMS} for pc386"
|
|
||||||
curl -L "https://github.com/mdavidsaver/rsb/releases/download/20171203-${RTEMS}/i386-rtems${RTEMS}-trusty-20171203-${RTEMS}.tar.bz2" \
|
|
||||||
| tar -C / -xmj
|
|
||||||
|
|
||||||
sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' epics-base/configure/os/CONFIG_SITE.Common.RTEMS
|
|
||||||
cat << EOF >> epics-base/configure/os/CONFIG_SITE.Common.RTEMS
|
|
||||||
RTEMS_VERSION=$RTEMS
|
|
||||||
RTEMS_BASE=$HOME/.rtems
|
|
||||||
EOF
|
|
||||||
cat << EOF >> epics-base/configure/CONFIG_SITE
|
|
||||||
CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386-qemu
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
make -j2 -C epics-base $EXTRA
|
|
||||||
301
.github/workflows/ci-scripts-build.yml
vendored
Normal file
301
.github/workflows/ci-scripts-build.yml
vendored
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
|
||||||
|
# (see: https://github.com/epics-base/ci-scripts)
|
||||||
|
|
||||||
|
# This is YAML - indentation levels are crucial
|
||||||
|
|
||||||
|
# Workflow name, shared by all branches
|
||||||
|
|
||||||
|
name: pvData
|
||||||
|
|
||||||
|
# Trigger on pushes and PRs to any branch
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths-ignore:
|
||||||
|
- .appveyor.yml
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
SETUP_PATH: .ci-local:.ci
|
||||||
|
EPICS_TEST_IMPRECISE_TIMING: YES
|
||||||
|
EPICS_TEST_TIMEOUT: 300 # 5 min
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
native:
|
||||||
|
name: ${{ matrix.name }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
# Set environment variables from matrix parameters
|
||||||
|
env:
|
||||||
|
# NB: PVA modules build against both BASE 7.0 and 3.15
|
||||||
|
BASE: ${{ matrix.base }}
|
||||||
|
CMP: ${{ matrix.cmp }}
|
||||||
|
BCFG: ${{ matrix.configuration }}
|
||||||
|
CI_CROSS_TARGETS: ${{ matrix.cross }}
|
||||||
|
EXTRA: ${{ matrix.extra }}
|
||||||
|
TEST: ${{ matrix.test }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
# Job names also name artifacts, character limitations apply
|
||||||
|
include:
|
||||||
|
- name: "7.0 Ub gcc c++20 Werror"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
# Turn all warnings into errors,
|
||||||
|
# except for those we could not fix (yet).
|
||||||
|
# Remove respective -Wno-error=... flag once it is fixed.
|
||||||
|
extra: "CMD_CXXFLAGS=-std=c++20
|
||||||
|
CMD_CPPFLAGS='-fdiagnostics-color
|
||||||
|
-fstack-protector-strong
|
||||||
|
-Wformat
|
||||||
|
-Werror
|
||||||
|
-Werror=format-security
|
||||||
|
-Wno-error=deprecated-declarations
|
||||||
|
-Wno-error=stringop-truncation
|
||||||
|
-Wno-error=restrict
|
||||||
|
-Wno-error=sizeof-pointer-memaccess
|
||||||
|
-Wno-error=nonnull
|
||||||
|
-Wno-error=dangling-pointer
|
||||||
|
-Wno-error=format-overflow
|
||||||
|
-Wno-error=stringop-overread
|
||||||
|
-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3'
|
||||||
|
CMD_LDFLAGS=-Wl,-z,relro"
|
||||||
|
|
||||||
|
- name: "7.0 Ub gcc C++11, static"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: gcc
|
||||||
|
configuration: static
|
||||||
|
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||||
|
|
||||||
|
- name: "7.0 Ub gcc u-char"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: gcc
|
||||||
|
configuration: static
|
||||||
|
extra: "CMD_CFLAGS=-funsigned-char CMD_CXXFLAGS=-funsigned-char"
|
||||||
|
|
||||||
|
- name: "7.0 Ub clang"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: clang
|
||||||
|
configuration: default
|
||||||
|
|
||||||
|
- name: "7.0 Ub clang C++11"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: clang
|
||||||
|
configuration: default
|
||||||
|
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||||
|
|
||||||
|
- name: "7.0 MacOS clang"
|
||||||
|
base: "7.0"
|
||||||
|
os: macos-latest
|
||||||
|
cmp: clang
|
||||||
|
configuration: default
|
||||||
|
|
||||||
|
# Cross builds
|
||||||
|
|
||||||
|
- name: "3.15 Ub-22 gcc + MinGW"
|
||||||
|
base: "3.15"
|
||||||
|
os: ubuntu-22.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
cross: "windows-x64-mingw"
|
||||||
|
|
||||||
|
- name: "7.0 Ub gcc + linux-aarch64"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
cross: "linux-aarch64"
|
||||||
|
|
||||||
|
- name: "7.0 Ub gcc + linux-arm gnueabi"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
cross: "linux-arm@arm-linux-gnueabi"
|
||||||
|
|
||||||
|
- name: "7.0 Ub gcc + linux-arm gnueabihf"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
cross: "linux-arm@arm-linux-gnueabihf"
|
||||||
|
|
||||||
|
- name: "7.0 Ub gcc + MinGW"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
cross: "windows-x64-mingw"
|
||||||
|
|
||||||
|
- name: "7.0 Ub gcc + MinGW, static"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-latest
|
||||||
|
cmp: gcc
|
||||||
|
configuration: static
|
||||||
|
cross: "windows-x64-mingw"
|
||||||
|
|
||||||
|
- name: "7.0 Ub-22 gcc + RT-4.9 pc386"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-22.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
cross: "RTEMS-pc386-qemu@4.9"
|
||||||
|
|
||||||
|
- name: "7.0 Ub-22 gcc + RT-4.10 pc386"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-22.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
cross: "RTEMS-pc386-qemu@4.10"
|
||||||
|
test: NO
|
||||||
|
|
||||||
|
- name: "7.0 Ub-22 gcc + RT-5.1 pc686"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-22.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
cross: "RTEMS-pc686-qemu@5"
|
||||||
|
|
||||||
|
- name: "7.0 Ub-22 gcc + RT-5.1 beatnik,zynq_a9,uC5282"
|
||||||
|
base: "7.0"
|
||||||
|
os: ubuntu-22.04
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
cross: "RTEMS-beatnik@5:RTEMS-xilinx_zynq_a9_qemu@5:RTEMS-uC5282@5"
|
||||||
|
test: NO
|
||||||
|
|
||||||
|
# Windows builds
|
||||||
|
|
||||||
|
- name: "7.0 Win-22 MSC-22"
|
||||||
|
base: "7.0"
|
||||||
|
os: windows-2022
|
||||||
|
cmp: vs2022
|
||||||
|
configuration: default
|
||||||
|
|
||||||
|
- name: "7.0 Win-22 MSC-22 static"
|
||||||
|
base: "7.0"
|
||||||
|
os: windows-2022
|
||||||
|
cmp: vs2022
|
||||||
|
configuration: static
|
||||||
|
|
||||||
|
- name: "7.0 Win-22 MSC-22 debug"
|
||||||
|
base: "7.0"
|
||||||
|
os: windows-2022
|
||||||
|
cmp: vs2022
|
||||||
|
configuration: debug
|
||||||
|
extra: "CMD_CXXFLAGS=-analyze"
|
||||||
|
|
||||||
|
- name: "7.0 Win-22 MinGW"
|
||||||
|
base: "7.0"
|
||||||
|
os: windows-2022
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- name: Automatic core dumper analysis
|
||||||
|
uses: mdavidsaver/ci-core-dumper@master
|
||||||
|
- name: "apt-get install"
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y install qemu-system-x86 g++-mingw-w64-x86-64 gdb
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
- name: Prepare and compile dependencies
|
||||||
|
run: python .ci/cue.py prepare
|
||||||
|
- name: Build main module
|
||||||
|
run: python .ci/cue.py build
|
||||||
|
- name: Run main module tests
|
||||||
|
run: python .ci/cue.py -T 60M test
|
||||||
|
- name: Upload tapfiles Artifact
|
||||||
|
if: ${{ always() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: tapfiles ${{ matrix.name }}
|
||||||
|
path: '**/O.*/*.tap'
|
||||||
|
if-no-files-found: ignore
|
||||||
|
- name: Collect and show test results
|
||||||
|
if: ${{ always() }}
|
||||||
|
run: python .ci/cue.py -T 5M test-results
|
||||||
|
|
||||||
|
docker:
|
||||||
|
name: ${{ matrix.name }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ${{ matrix.image }}
|
||||||
|
# Set environment variables from matrix parameters
|
||||||
|
env:
|
||||||
|
BASE: ${{ matrix.base }}
|
||||||
|
CMP: ${{ matrix.cmp }}
|
||||||
|
BCFG: ${{ matrix.configuration }}
|
||||||
|
EXTRA: ${{ matrix.extra }}
|
||||||
|
TEST: ${{ matrix.test }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
# Job names also name artifacts, character limitations apply
|
||||||
|
include:
|
||||||
|
- name: "7.0 CentOS-8 gcc"
|
||||||
|
base: "7.0"
|
||||||
|
image: centos:8
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
|
||||||
|
- name: "7.0 Rocky-9 gcc"
|
||||||
|
base: "7.0"
|
||||||
|
image: rockylinux:9
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
|
||||||
|
- name: "7.0 Fedora-33 gcc"
|
||||||
|
base: "7.0"
|
||||||
|
image: fedora:33
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
|
||||||
|
- name: "7.0 Fedora gcc"
|
||||||
|
base: "7.0"
|
||||||
|
image: fedora:latest
|
||||||
|
cmp: gcc
|
||||||
|
configuration: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: "Fix repo URLs on CentOS-8"
|
||||||
|
# centos:8 is frozen, repos are in the vault
|
||||||
|
if: matrix.image=='centos:8'
|
||||||
|
run: |
|
||||||
|
sed -i -e "s|mirrorlist=|#mirrorlist=|" \
|
||||||
|
-e "s|#baseurl=http://mirror|baseurl=http://vault|" \
|
||||||
|
/etc/yum.repos.d/CentOS-Linux-{BaseOS,AppStream,Extras,Plus}.repo
|
||||||
|
- name: "Redhat setup"
|
||||||
|
run: |
|
||||||
|
dnf -y install python3 gdb make perl gcc-c++ glibc-devel readline-devel ncurses-devel perl-devel perl-Test-Simple
|
||||||
|
git --version || dnf -y install git
|
||||||
|
python3 --version
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- name: Automatic core dumper analysis
|
||||||
|
uses: mdavidsaver/ci-core-dumper@master
|
||||||
|
- name: Prepare and compile dependencies
|
||||||
|
run: python3 .ci/cue.py prepare
|
||||||
|
- name: Build main module
|
||||||
|
run: python3 .ci/cue.py build
|
||||||
|
- name: Run main module tests
|
||||||
|
run: python3 .ci/cue.py -T 20M test
|
||||||
|
- name: Upload tapfiles Artifact
|
||||||
|
if: ${{ always() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: tapfiles ${{ matrix.name }}
|
||||||
|
path: '**/O.*/*.tap'
|
||||||
|
if-no-files-found: ignore
|
||||||
|
- name: Collect and show test results
|
||||||
|
if: ${{ always() }}
|
||||||
|
run: python3 .ci/cue.py -T 5M test-results
|
||||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule ".ci"]
|
||||||
|
path = .ci
|
||||||
|
url = https://github.com/epics-base/ci-scripts
|
||||||
17
.readthedocs.yml
Normal file
17
.readthedocs.yml
Normal 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
|
||||||
30
.travis.yml
30
.travis.yml
@@ -1,30 +0,0 @@
|
|||||||
sudo: false
|
|
||||||
dist: trusty
|
|
||||||
language: c++
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libreadline6-dev
|
|
||||||
- libncurses5-dev
|
|
||||||
- perl
|
|
||||||
- clang
|
|
||||||
- g++-mingw-w64-i686
|
|
||||||
- qemu-system-x86
|
|
||||||
install:
|
|
||||||
- ./.ci/travis-prepare.sh
|
|
||||||
script:
|
|
||||||
- ./.ci/travis-build.sh
|
|
||||||
env:
|
|
||||||
- BRBASE=7.0 CMPLR=gcc
|
|
||||||
- BRBASE=7.0 CMPLR=clang
|
|
||||||
- BRBASE=7.0 USR_CXXFLAGS=-std=c++11
|
|
||||||
- BRBASE=7.0 CMPLR=clang USR_CXXFLAGS=-std=c++11
|
|
||||||
- BRBASE=7.0 WINE=32 TEST=NO STATIC=YES
|
|
||||||
- BRBASE=7.0 WINE=32 TEST=NO STATIC=NO
|
|
||||||
- BRBASE=7.0 RTEMS=4.10 TEST=NO
|
|
||||||
- BRBASE=7.0 RTEMS=4.9 TEST=NO
|
|
||||||
- BRBASE=3.16
|
|
||||||
- BRBASE=3.15
|
|
||||||
- BRBASE=3.14
|
|
||||||
210
Doxyfile
210
Doxyfile
@@ -1,4 +1,4 @@
|
|||||||
# Doxyfile 1.8.6
|
# Doxyfile 1.8.8
|
||||||
|
|
||||||
# This file describes the settings to be used by the documentation system
|
# This file describes the settings to be used by the documentation system
|
||||||
# doxygen (www.doxygen.org) for a project.
|
# doxygen (www.doxygen.org) for a project.
|
||||||
@@ -32,13 +32,13 @@ DOXYFILE_ENCODING = UTF-8
|
|||||||
# title of most generated pages and in a few other places.
|
# title of most generated pages and in a few other places.
|
||||||
# The default value is: My Project.
|
# The default value is: My Project.
|
||||||
|
|
||||||
PROJECT_NAME = pvDataCPP
|
PROJECT_NAME = "PVData C++"
|
||||||
|
|
||||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER =
|
PROJECT_NUMBER = 8.0.8-dev
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# 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
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
@@ -58,7 +58,7 @@ PROJECT_LOGO =
|
|||||||
# entered, it will be relative to the location where doxygen was started. If
|
# entered, it will be relative to the location where doxygen was started. If
|
||||||
# left blank the current directory will be used.
|
# left blank the current directory will be used.
|
||||||
|
|
||||||
OUTPUT_DIRECTORY =
|
OUTPUT_DIRECTORY = .
|
||||||
|
|
||||||
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
|
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
|
||||||
# directories (in 2 levels) under the output directory of each output format and
|
# directories (in 2 levels) under the output directory of each output format and
|
||||||
@@ -70,6 +70,14 @@ OUTPUT_DIRECTORY =
|
|||||||
|
|
||||||
CREATE_SUBDIRS = NO
|
CREATE_SUBDIRS = NO
|
||||||
|
|
||||||
|
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
|
||||||
|
# characters to appear in the names of generated files. If set to NO, non-ASCII
|
||||||
|
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
|
||||||
|
# U+3044.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
ALLOW_UNICODE_NAMES = NO
|
||||||
|
|
||||||
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
|
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
|
||||||
# documentation generated by doxygen is written. Doxygen will use this
|
# documentation generated by doxygen is written. Doxygen will use this
|
||||||
# information to generate all constant output in the proper language.
|
# information to generate all constant output in the proper language.
|
||||||
@@ -110,7 +118,17 @@ REPEAT_BRIEF = YES
|
|||||||
# the entity):The $name class, The $name widget, The $name file, is, provides,
|
# the entity):The $name class, The $name widget, The $name file, is, provides,
|
||||||
# specifies, contains, represents, a, an and the.
|
# specifies, contains, represents, a, an and the.
|
||||||
|
|
||||||
ABBREVIATE_BRIEF =
|
ABBREVIATE_BRIEF = "The $name class" \
|
||||||
|
"The $name widget" \
|
||||||
|
"The $name file" \
|
||||||
|
is \
|
||||||
|
provides \
|
||||||
|
specifies \
|
||||||
|
contains \
|
||||||
|
represents \
|
||||||
|
a \
|
||||||
|
an \
|
||||||
|
the
|
||||||
|
|
||||||
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
|
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
|
||||||
# doxygen will generate a detailed section even if there is only a brief
|
# doxygen will generate a detailed section even if there is only a brief
|
||||||
@@ -125,7 +143,7 @@ ALWAYS_DETAILED_SEC = NO
|
|||||||
# operators of the base classes will not be shown.
|
# operators of the base classes will not be shown.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
INLINE_INHERITED_MEMB = YES
|
INLINE_INHERITED_MEMB = NO
|
||||||
|
|
||||||
# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
|
# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
|
||||||
# before files name in the file list and in the header files. If set to NO the
|
# before files name in the file list and in the header files. If set to NO the
|
||||||
@@ -144,7 +162,7 @@ FULL_PATH_NAMES = YES
|
|||||||
# will be relative from the directory where doxygen is started.
|
# will be relative from the directory where doxygen is started.
|
||||||
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
|
# 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
|
# 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
|
# path mentioned in the documentation of a class, which tells the reader which
|
||||||
@@ -153,7 +171,7 @@ STRIP_FROM_PATH =
|
|||||||
# specify the list of include paths that are normally passed to the compiler
|
# specify the list of include paths that are normally passed to the compiler
|
||||||
# using the -I flag.
|
# 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
|
# 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
|
# less readable) file names. This can be useful is your file systems doesn't
|
||||||
@@ -261,9 +279,12 @@ OPTIMIZE_OUTPUT_VHDL = NO
|
|||||||
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
# extension. Doxygen has a built-in mapping, but you can override or extend it
|
||||||
# using this tag. The format is ext=language, where ext is a file extension, and
|
# using this tag. The format is ext=language, where ext is a file extension, and
|
||||||
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
|
||||||
# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
|
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
|
||||||
# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
|
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
|
||||||
# (default is Fortran), use: inc=Fortran f=C.
|
# Fortran. In the later case the parser tries to guess whether the code is fixed
|
||||||
|
# or free formatted code, this is the default for Fortran type files), VHDL. For
|
||||||
|
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
|
||||||
|
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
|
||||||
#
|
#
|
||||||
# Note For files without extension you can use no_extension as a placeholder.
|
# Note For files without extension you can use no_extension as a placeholder.
|
||||||
#
|
#
|
||||||
@@ -298,7 +319,7 @@ AUTOLINK_SUPPORT = YES
|
|||||||
# diagrams that involve STL classes more complete and accurate.
|
# diagrams that involve STL classes more complete and accurate.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
BUILTIN_STL_SUPPORT = YES
|
BUILTIN_STL_SUPPORT = NO
|
||||||
|
|
||||||
# If you use Microsoft's C++/CLI language, you should set this option to YES to
|
# If you use Microsoft's C++/CLI language, you should set this option to YES to
|
||||||
# enable parsing support.
|
# enable parsing support.
|
||||||
@@ -398,7 +419,7 @@ LOOKUP_CACHE_SIZE = 0
|
|||||||
# normally produced when WARNINGS is set to YES.
|
# normally produced when WARNINGS is set to YES.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
EXTRACT_ALL = YES
|
EXTRACT_ALL = NO
|
||||||
|
|
||||||
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
|
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
|
||||||
# be included in the documentation.
|
# be included in the documentation.
|
||||||
@@ -487,7 +508,7 @@ INTERNAL_DOCS = NO
|
|||||||
# and Mac users are advised to set this option to NO.
|
# and Mac users are advised to set this option to NO.
|
||||||
# The default value is: system dependent.
|
# The default value is: system dependent.
|
||||||
|
|
||||||
CASE_SENSE_NAMES = YES
|
CASE_SENSE_NAMES = NO
|
||||||
|
|
||||||
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
|
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
|
||||||
# their full class and namespace scopes in the documentation. If set to YES the
|
# their full class and namespace scopes in the documentation. If set to YES the
|
||||||
@@ -669,8 +690,7 @@ LAYOUT_FILE =
|
|||||||
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
|
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
|
||||||
# For LaTeX the style of the bibliography can be controlled using
|
# For LaTeX the style of the bibliography can be controlled using
|
||||||
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
|
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
|
||||||
# search path. Do not use file names with spaces, bibtex cannot handle them. See
|
# search path. See also \cite for info how to create references.
|
||||||
# also \cite for info how to create references.
|
|
||||||
|
|
||||||
CITE_BIB_FILES =
|
CITE_BIB_FILES =
|
||||||
|
|
||||||
@@ -699,7 +719,7 @@ WARNINGS = YES
|
|||||||
# will automatically be disabled.
|
# will automatically be disabled.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
WARN_IF_UNDOCUMENTED = YES
|
WARN_IF_UNDOCUMENTED = NO
|
||||||
|
|
||||||
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
|
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
|
||||||
# potential errors in the documentation, such as not documenting some parameters
|
# potential errors in the documentation, such as not documenting some parameters
|
||||||
@@ -743,7 +763,12 @@ WARN_LOGFILE =
|
|||||||
# spaces.
|
# spaces.
|
||||||
# Note: If this tag is empty the current directory is searched.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = include
|
INPUT = src/pv \
|
||||||
|
documentation/mainpage.dox \
|
||||||
|
src/copy/pv \
|
||||||
|
src/misc/pv \
|
||||||
|
src/json/pv \
|
||||||
|
documentation/release_notes.dox
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# 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
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
@@ -769,7 +794,7 @@ FILE_PATTERNS =
|
|||||||
# be searched for input files as well.
|
# be searched for input files as well.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
RECURSIVE = YES
|
RECURSIVE = NO
|
||||||
|
|
||||||
# The EXCLUDE tag can be used to specify files and/or directories that should be
|
# 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
|
# excluded from the INPUT source files. This way you can easily exclude a
|
||||||
@@ -811,14 +836,14 @@ EXCLUDE_SYMBOLS =
|
|||||||
# that contain example code fragments that are included (see the \include
|
# that contain example code fragments that are included (see the \include
|
||||||
# command).
|
# command).
|
||||||
|
|
||||||
EXAMPLE_PATH =
|
EXAMPLE_PATH = examples
|
||||||
|
|
||||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
|
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
|
||||||
# *.h) to filter out the source-files in the directories. If left blank all
|
# *.h) to filter out the source-files in the directories. If left blank all
|
||||||
# files are included.
|
# files are included.
|
||||||
|
|
||||||
EXAMPLE_PATTERNS =
|
EXAMPLE_PATTERNS = *.cpp
|
||||||
|
|
||||||
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
|
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
|
||||||
# searched for input files to be used with the \include or \dontinclude commands
|
# searched for input files to be used with the \include or \dontinclude commands
|
||||||
@@ -911,13 +936,13 @@ STRIP_CODE_COMMENTS = YES
|
|||||||
# function all documented functions referencing it will be listed.
|
# function all documented functions referencing it will be listed.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
REFERENCED_BY_RELATION = YES
|
REFERENCED_BY_RELATION = NO
|
||||||
|
|
||||||
# If the REFERENCES_RELATION tag is set to YES then for each documented function
|
# If the REFERENCES_RELATION tag is set to YES then for each documented function
|
||||||
# all documented entities called/used by that function will be listed.
|
# all documented entities called/used by that function will be listed.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
REFERENCES_RELATION = YES
|
REFERENCES_RELATION = NO
|
||||||
|
|
||||||
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
|
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
|
||||||
# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
|
# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
|
||||||
@@ -967,6 +992,25 @@ USE_HTAGS = NO
|
|||||||
|
|
||||||
VERBATIM_HEADERS = YES
|
VERBATIM_HEADERS = YES
|
||||||
|
|
||||||
|
# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
|
||||||
|
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
|
||||||
|
# cost of reduced performance. This can be particularly helpful with template
|
||||||
|
# rich C++ code for which doxygen's built-in parser lacks the necessary type
|
||||||
|
# information.
|
||||||
|
# Note: The availability of this option depends on whether or not doxygen was
|
||||||
|
# compiled with the --with-libclang option.
|
||||||
|
# The default value is: NO.
|
||||||
|
|
||||||
|
CLANG_ASSISTED_PARSING = YES
|
||||||
|
|
||||||
|
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||||
|
# line options that you would normally use when invoking the compiler. Note that
|
||||||
|
# the include paths will already be set by doxygen for the files and directories
|
||||||
|
# specified with INPUT and INCLUDE_PATH.
|
||||||
|
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||||
|
|
||||||
|
CLANG_OPTIONS =
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the alphabetical class index
|
# Configuration options related to the alphabetical class index
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@@ -976,7 +1020,7 @@ VERBATIM_HEADERS = YES
|
|||||||
# classes, structs, unions or interfaces.
|
# classes, structs, unions or interfaces.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
ALPHABETICAL_INDEX = NO
|
ALPHABETICAL_INDEX = YES
|
||||||
|
|
||||||
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
|
||||||
# which the alphabetical index list will be split.
|
# which the alphabetical index list will be split.
|
||||||
@@ -1008,7 +1052,7 @@ GENERATE_HTML = YES
|
|||||||
# The default directory is: html.
|
# The default directory is: html.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# 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
|
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
||||||
# generated HTML page (for example: .htm, .php, .asp).
|
# generated HTML page (for example: .htm, .php, .asp).
|
||||||
@@ -1059,13 +1103,15 @@ HTML_FOOTER =
|
|||||||
|
|
||||||
HTML_STYLESHEET =
|
HTML_STYLESHEET =
|
||||||
|
|
||||||
# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
|
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
|
||||||
# defined cascading style sheet that is included after the standard style sheets
|
# cascading style sheets that are included after the standard style sheets
|
||||||
# created by doxygen. Using this option one can overrule certain style aspects.
|
# created by doxygen. Using this option one can overrule certain style aspects.
|
||||||
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
||||||
# standard style sheet and is therefor more robust against future updates.
|
# standard style sheet and is therefor more robust against future updates.
|
||||||
# Doxygen will copy the style sheet file to the output directory. For an example
|
# Doxygen will copy the style sheet files to the output directory.
|
||||||
# see the documentation.
|
# Note: The order of the extra stylesheet files is of importance (e.g. the last
|
||||||
|
# stylesheet in the list overrules the setting of the previous ones in the
|
||||||
|
# list). For an example see the documentation.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_EXTRA_STYLESHEET =
|
HTML_EXTRA_STYLESHEET =
|
||||||
@@ -1078,7 +1124,7 @@ HTML_EXTRA_STYLESHEET =
|
|||||||
# files will be copied as-is; there are no commands or markers available.
|
# files will be copied as-is; there are no commands or markers available.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_EXTRA_FILES = documentation/pvDataCPP.html
|
HTML_EXTRA_FILES =
|
||||||
|
|
||||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||||
# will adjust the colors in the stylesheet and background images according to
|
# will adjust the colors in the stylesheet and background images according to
|
||||||
@@ -1230,7 +1276,8 @@ GENERATE_CHI = NO
|
|||||||
CHM_INDEX_ENCODING =
|
CHM_INDEX_ENCODING =
|
||||||
|
|
||||||
# The BINARY_TOC flag controls whether a binary table of contents is generated (
|
# The BINARY_TOC flag controls whether a binary table of contents is generated (
|
||||||
# YES) or a normal table of contents ( NO) in the .chm file.
|
# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
|
||||||
|
# enables the Previous and Next buttons.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
|
||||||
|
|
||||||
@@ -1466,15 +1513,15 @@ MATHJAX_CODEFILE =
|
|||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
SEARCHENGINE = NO
|
SEARCHENGINE = YES
|
||||||
|
|
||||||
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
|
||||||
# implemented using a web server instead of a web client using Javascript. There
|
# implemented using a web server instead of a web client using Javascript. There
|
||||||
# are two flavours of web server based searching depending on the
|
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
|
||||||
# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
|
# setting. When disabled, doxygen will generate a PHP script for searching and
|
||||||
# searching and an index file used by the script. When EXTERNAL_SEARCH is
|
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
|
||||||
# enabled the indexing and searching needs to be provided by external tools. See
|
# and searching needs to be provided by external tools. See the section
|
||||||
# the section "External Indexing and Searching" for details.
|
# "External Indexing and Searching" for details.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag SEARCHENGINE is set to YES.
|
# This tag requires that the tag SEARCHENGINE is set to YES.
|
||||||
|
|
||||||
@@ -1583,7 +1630,7 @@ COMPACT_LATEX = NO
|
|||||||
# The default value is: a4.
|
# The default value is: a4.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
PAPER_TYPE = a4wide
|
PAPER_TYPE = a4
|
||||||
|
|
||||||
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
|
||||||
# that should be included in the LaTeX output. To get the times font for
|
# that should be included in the LaTeX output. To get the times font for
|
||||||
@@ -1602,17 +1649,19 @@ EXTRA_PACKAGES =
|
|||||||
#
|
#
|
||||||
# Note: Only use a user-defined header if you know what you are doing! The
|
# Note: Only use a user-defined header if you know what you are doing! The
|
||||||
# following commands have a special meaning inside the header: $title,
|
# following commands have a special meaning inside the header: $title,
|
||||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
|
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
||||||
# replace them by respectively the title of the page, the current date and time,
|
# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
|
||||||
# only the current date, the version number of doxygen, the project name (see
|
# for the replacement values of the other commands the user is refered to
|
||||||
# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
|
# HTML_HEADER.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
LATEX_HEADER =
|
LATEX_HEADER =
|
||||||
|
|
||||||
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
|
||||||
# generated LaTeX document. The footer should contain everything after the last
|
# generated LaTeX document. The footer should contain everything after the last
|
||||||
# chapter. If it is left blank doxygen will generate a standard footer.
|
# chapter. If it is left blank doxygen will generate a standard footer. See
|
||||||
|
# LATEX_HEADER for more information on how to generate a default footer and what
|
||||||
|
# special commands can be used inside the footer.
|
||||||
#
|
#
|
||||||
# Note: Only use a user-defined footer if you know what you are doing!
|
# Note: Only use a user-defined footer if you know what you are doing!
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
@@ -1634,15 +1683,15 @@ LATEX_EXTRA_FILES =
|
|||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
PDF_HYPERLINKS = NO
|
PDF_HYPERLINKS = YES
|
||||||
|
|
||||||
# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
|
||||||
# the PDF file directly from the LaTeX files. Set this option to YES to get a
|
# the PDF file directly from the LaTeX files. Set this option to YES to get a
|
||||||
# higher quality PDF documentation.
|
# higher quality PDF documentation.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||||
|
|
||||||
USE_PDFLATEX = NO
|
USE_PDFLATEX = YES
|
||||||
|
|
||||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
||||||
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
||||||
@@ -1762,6 +1811,13 @@ MAN_OUTPUT = man
|
|||||||
|
|
||||||
MAN_EXTENSION = .3
|
MAN_EXTENSION = .3
|
||||||
|
|
||||||
|
# The MAN_SUBDIR tag determines the name of the directory created within
|
||||||
|
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
|
||||||
|
# MAN_EXTENSION with the initial . removed.
|
||||||
|
# This tag requires that the tag GENERATE_MAN is set to YES.
|
||||||
|
|
||||||
|
MAN_SUBDIR =
|
||||||
|
|
||||||
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
|
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
|
||||||
# will generate one additional man file for each entity documented in the real
|
# will generate one additional man file for each entity documented in the real
|
||||||
# man page(s). These additional files only source the real man page, but without
|
# man page(s). These additional files only source the real man page, but without
|
||||||
@@ -1789,18 +1845,6 @@ GENERATE_XML = NO
|
|||||||
|
|
||||||
XML_OUTPUT = xml
|
XML_OUTPUT = xml
|
||||||
|
|
||||||
# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
|
|
||||||
# validating XML parser to check the syntax of the XML files.
|
|
||||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
|
||||||
|
|
||||||
XML_SCHEMA =
|
|
||||||
|
|
||||||
# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
|
|
||||||
# validating XML parser to check the syntax of the XML files.
|
|
||||||
# This tag requires that the tag GENERATE_XML is set to YES.
|
|
||||||
|
|
||||||
XML_DTD =
|
|
||||||
|
|
||||||
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
|
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
|
||||||
# listings (including syntax highlighting and cross-referencing information) to
|
# listings (including syntax highlighting and cross-referencing information) to
|
||||||
# the XML output. Note that enabling this will significantly increase the size
|
# the XML output. Note that enabling this will significantly increase the size
|
||||||
@@ -1828,6 +1872,15 @@ GENERATE_DOCBOOK = NO
|
|||||||
|
|
||||||
DOCBOOK_OUTPUT = docbook
|
DOCBOOK_OUTPUT = docbook
|
||||||
|
|
||||||
|
# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
|
||||||
|
# program listings (including syntax highlighting and cross-referencing
|
||||||
|
# information) to the DOCBOOK output. Note that enabling this will significantly
|
||||||
|
# increase the size of the DOCBOOK output.
|
||||||
|
# The default value is: NO.
|
||||||
|
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
|
||||||
|
|
||||||
|
DOCBOOK_PROGRAMLISTING = NO
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options for the AutoGen Definitions output
|
# Configuration options for the AutoGen Definitions output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@@ -1895,7 +1948,7 @@ ENABLE_PREPROCESSING = YES
|
|||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||||
|
|
||||||
MACRO_EXPANSION = NO
|
MACRO_EXPANSION = YES
|
||||||
|
|
||||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
|
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
|
||||||
# the macro expansion is limited to the macros specified with the PREDEFINED and
|
# the macro expansion is limited to the macros specified with the PREDEFINED and
|
||||||
@@ -1917,7 +1970,7 @@ SEARCH_INCLUDES = YES
|
|||||||
# preprocessor.
|
# preprocessor.
|
||||||
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
|
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
|
||||||
|
|
||||||
INCLUDE_PATH =
|
INCLUDE_PATH = src/misc src ../../include/
|
||||||
|
|
||||||
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
|
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
|
||||||
# patterns (like *.h and *.hpp) to filter out the header-files in the
|
# patterns (like *.h and *.hpp) to filter out the header-files in the
|
||||||
@@ -1947,14 +2000,14 @@ PREDEFINED =
|
|||||||
EXPAND_AS_DEFINED =
|
EXPAND_AS_DEFINED =
|
||||||
|
|
||||||
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
|
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
|
||||||
# remove all refrences to function-like macros that are alone on a line, have an
|
# remove all references to function-like macros that are alone on a line, have
|
||||||
# all uppercase name, and do not end with a semicolon. Such function macros are
|
# an all uppercase name, and do not end with a semicolon. Such function macros
|
||||||
# typically used for boiler-plate code, and will confuse the parser if not
|
# are typically used for boiler-plate code, and will confuse the parser if not
|
||||||
# removed.
|
# removed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||||
|
|
||||||
SKIP_FUNCTION_MACROS = YES
|
SKIP_FUNCTION_MACROS = NO
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to external references
|
# Configuration options related to external references
|
||||||
@@ -1969,17 +2022,17 @@ SKIP_FUNCTION_MACROS = YES
|
|||||||
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
|
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
|
||||||
# section "Linking to external documentation" for more information about the use
|
# section "Linking to external documentation" for more information about the use
|
||||||
# of tag files.
|
# of tag files.
|
||||||
# Note: Each tag file must have an unique name (where the name does NOT include
|
# Note: Each tag file must have a unique name (where the name does NOT include
|
||||||
# the path). If a tag file is not located in the directory in which doxygen is
|
# the path). If a tag file is not located in the directory in which doxygen is
|
||||||
# run, you must also specify the path to the tagfile here.
|
# run, you must also specify the path to the tagfile here.
|
||||||
|
|
||||||
TAGFILES =
|
TAGFILES = "libstdc++.tag = http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen"
|
||||||
|
|
||||||
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
|
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
|
||||||
# tag file that is based on the input files it reads. See section "Linking to
|
# tag file that is based on the input files it reads. See section "Linking to
|
||||||
# external documentation" for more information about the usage of tag files.
|
# external documentation" for more information about the usage of tag files.
|
||||||
|
|
||||||
GENERATE_TAGFILE =
|
GENERATE_TAGFILE = pvdata.tag
|
||||||
|
|
||||||
# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
|
# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
|
||||||
# class index. If set to NO only the inherited external classes will be listed.
|
# class index. If set to NO only the inherited external classes will be listed.
|
||||||
@@ -1992,14 +2045,14 @@ ALLEXTERNALS = NO
|
|||||||
# listed.
|
# listed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
EXTERNAL_GROUPS = YES
|
EXTERNAL_GROUPS = NO
|
||||||
|
|
||||||
# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
|
# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
|
||||||
# the related pages index. If set to NO, only the current project's pages will
|
# the related pages index. If set to NO, only the current project's pages will
|
||||||
# be listed.
|
# be listed.
|
||||||
# The default value is: YES.
|
# The default value is: YES.
|
||||||
|
|
||||||
EXTERNAL_PAGES = YES
|
EXTERNAL_PAGES = NO
|
||||||
|
|
||||||
# The PERL_PATH should be the absolute path and name of the perl script
|
# The PERL_PATH should be the absolute path and name of the perl script
|
||||||
# interpreter (i.e. the result of 'which perl').
|
# interpreter (i.e. the result of 'which perl').
|
||||||
@@ -2047,9 +2100,9 @@ HIDE_UNDOC_RELATIONS = YES
|
|||||||
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
|
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
|
||||||
# Bell Labs. The other options in this section have no effect if this option is
|
# Bell Labs. The other options in this section have no effect if this option is
|
||||||
# set to NO
|
# set to NO
|
||||||
# The default value is: NO.
|
# The default value is: YES.
|
||||||
|
|
||||||
HAVE_DOT = NO
|
HAVE_DOT = YES
|
||||||
|
|
||||||
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
|
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
|
||||||
# to run in parallel. When set to 0 doxygen will base this on the number of
|
# to run in parallel. When set to 0 doxygen will base this on the number of
|
||||||
@@ -2061,7 +2114,7 @@ HAVE_DOT = NO
|
|||||||
|
|
||||||
DOT_NUM_THREADS = 0
|
DOT_NUM_THREADS = 0
|
||||||
|
|
||||||
# When you want a differently looking font n the dot files that doxygen
|
# When you want a differently looking font in the dot files that doxygen
|
||||||
# generates you can specify the font name using DOT_FONTNAME. You need to make
|
# generates you can specify the font name using DOT_FONTNAME. You need to make
|
||||||
# sure dot is able to find the font, which can be done by putting it in a
|
# sure dot is able to find the font, which can be done by putting it in a
|
||||||
# standard location or by setting the DOTFONTPATH environment variable or by
|
# standard location or by setting the DOTFONTPATH environment variable or by
|
||||||
@@ -2199,7 +2252,9 @@ DIRECTORY_GRAPH = YES
|
|||||||
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
||||||
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
||||||
# requirement).
|
# requirement).
|
||||||
# Possible values are: png, jpg, gif and svg.
|
# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
|
||||||
|
# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
|
||||||
|
# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
|
||||||
# The default value is: png.
|
# The default value is: png.
|
||||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
@@ -2242,6 +2297,15 @@ MSCFILE_DIRS =
|
|||||||
|
|
||||||
DIAFILE_DIRS =
|
DIAFILE_DIRS =
|
||||||
|
|
||||||
|
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
|
||||||
|
# path where java can find the plantuml.jar file. If left blank, it is assumed
|
||||||
|
# PlantUML is not used or called during a preprocessing step. Doxygen will
|
||||||
|
# generate a warning when it encounters a \startuml command in this case and
|
||||||
|
# will not generate output for the diagram.
|
||||||
|
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||||
|
|
||||||
|
PLANTUML_JAR_PATH =
|
||||||
|
|
||||||
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
|
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
|
||||||
# that will be shown in the graph. If the number of nodes in a graph becomes
|
# that will be shown in the graph. If the number of nodes in a graph becomes
|
||||||
# larger than this value, doxygen will truncate the graph, which is visualized
|
# larger than this value, doxygen will truncate the graph, which is visualized
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
|
# Version number for the PV Data API and shared library
|
||||||
|
|
||||||
EPICS_PVD_MAJOR_VERSION = 8
|
EPICS_PVD_MAJOR_VERSION = 8
|
||||||
EPICS_PVD_MINOR_VERSION = 0
|
EPICS_PVD_MINOR_VERSION = 0
|
||||||
EPICS_PVD_MAINTENANCE_VERSION = 0
|
EPICS_PVD_MAINTENANCE_VERSION = 8
|
||||||
EPICS_PVD_DEVELOPMENT_FLAG = 0
|
|
||||||
|
# Development flag, set to zero for release versions
|
||||||
|
|
||||||
|
EPICS_PVD_DEVELOPMENT_FLAG = 1
|
||||||
|
|
||||||
|
# Immediately after a release the MAINTENANCE_VERSION
|
||||||
|
# will be incremented and the DEVELOPMENT_FLAG set to 1
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ PROJECT_NAME = "PVData C++"
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 8.0.0
|
PROJECT_NUMBER = 8.0.8-dev
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# 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
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
|
|||||||
7
documentation/_static/css/custom.css
Normal file
7
documentation/_static/css/custom.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.wy-side-nav-search {
|
||||||
|
background-color: #18334B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-side-nav-search input[type="text"] {
|
||||||
|
border-color: #18334b;
|
||||||
|
}
|
||||||
78
documentation/conf.py
Normal file
78
documentation/conf.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# 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 = 'EPICS Documentation'
|
||||||
|
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 = {
|
||||||
|
'how-tos': ('https://docs.epics-controls.org/projects/how-tos/en/latest', None),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# -- 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']
|
||||||
|
|
||||||
|
|
||||||
|
# -- Run Doxygen ------------------------------------------------------------
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)
|
||||||
BIN
documentation/images/EPICS_white_logo_v02.png
Normal file
BIN
documentation/images/EPICS_white_logo_v02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
16
documentation/index.rst
Normal file
16
documentation/index.rst
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
pvData (C++) Library
|
||||||
|
====================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
EPICS Website <https://epics-controls.org>
|
||||||
|
EPICS Documentation Home <https://docs.epics-controls.org>
|
||||||
|
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:caption: pvDataCPP
|
||||||
|
|
||||||
|
Reference Manual and API Documentation <https://docs.epics-controls.org/projects/pvdata-cpp/en/latest/doxygen>
|
||||||
|
Source Code Repository on GitHub <https://github.com/epics-base/pvDataCPP>
|
||||||
@@ -2,16 +2,68 @@
|
|||||||
|
|
||||||
@page release_notes Release Notes
|
@page release_notes Release Notes
|
||||||
|
|
||||||
|
Release 8.0.7 (Dec 2025)
|
||||||
|
========================
|
||||||
|
|
||||||
|
- Compatible changes
|
||||||
|
- Allow epics::pvData::Timer to be cancelled during callback execution.
|
||||||
|
- Clang compiler warnings cleaned up.
|
||||||
|
- Limit periodic timers to one catch-up after missing many events.
|
||||||
|
|
||||||
|
Release 8.0.6 (Dec 2023)
|
||||||
|
========================
|
||||||
|
|
||||||
|
- Compatible changes
|
||||||
|
- Actually enable JSON-5 output in PVStructure::Formatter::JSON when available.
|
||||||
|
- Fix unaligned access issues for some ARM/Linux targets.
|
||||||
|
|
||||||
|
Release 8.0.5 (Sep 2022)
|
||||||
|
========================
|
||||||
|
|
||||||
|
- Compatible changes
|
||||||
|
- Internal changes to use the YAJL API for generating JSON and JSON-5 output.
|
||||||
|
|
||||||
|
Release 8.0.4 (Feb 2021)
|
||||||
|
========================
|
||||||
|
|
||||||
|
- Incompatible changes
|
||||||
|
- Remove ByteBuffer::align()
|
||||||
|
- Compatible changes
|
||||||
|
- Deprecate SerializableControl::alignBuffer() and DeserializableControl::alignData()
|
||||||
|
- shared_vector_convert<>() fix convert of empty, untyped, array
|
||||||
|
|
||||||
|
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)
|
||||||
|
========================
|
||||||
|
|
||||||
|
- Changes to documentation and unittests.
|
||||||
|
No functional changes to library.
|
||||||
|
|
||||||
|
Release 8.0.1 (Nov 2019)
|
||||||
|
==========================
|
||||||
|
|
||||||
|
- Incompatible changes
|
||||||
|
- Requires Base >= 3.15
|
||||||
|
- Bug fixes
|
||||||
|
|
||||||
Release 8.0.0 (July 2019)
|
Release 8.0.0 (July 2019)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
- Deprecations
|
- Deprecations
|
||||||
- ByteBuffer::getArray()
|
- ByteBuffer::getArray()
|
||||||
- Removals
|
- Removals
|
||||||
- pv/localStaticLock.h
|
- pv/localStaticLock.h
|
||||||
- pv/pvCopy.h (see epics::pvData::PVRequestMapper)
|
- pv/pvCopy.h (see epics::pvData::PVRequestMapper)
|
||||||
- Additions
|
- Additions
|
||||||
- Add {Structure,Union}::getFieldT
|
- Add {Structure,Union}::getFieldT
|
||||||
|
|
||||||
Release 7.1.3 (Apr 2019)
|
Release 7.1.3 (Apr 2019)
|
||||||
========================
|
========================
|
||||||
@@ -28,60 +80,60 @@ Release 7.1.1 (Mar 2019)
|
|||||||
========================
|
========================
|
||||||
|
|
||||||
- Fixes
|
- Fixes
|
||||||
- Init order issue with StandardField::getStandardField()
|
- Init order issue with StandardField::getStandardField()
|
||||||
- Build fix for Visual Studio 2013+
|
- Build fix for Visual Studio 2013+
|
||||||
|
|
||||||
Release 7.1.0 (Nov 2018)
|
Release 7.1.0 (Nov 2018)
|
||||||
========================
|
========================
|
||||||
|
|
||||||
- Deprecations
|
- Deprecations
|
||||||
- BoundedString, BoundedScalarArray, and FixedScalarArray will be removed unless they are fixed.
|
- BoundedString, BoundedScalarArray, and FixedScalarArray will be removed unless they are fixed.
|
||||||
See https://github.com/epics-base/pvDataCPP/issues/52 for discussion.
|
See https://github.com/epics-base/pvDataCPP/issues/52 for discussion.
|
||||||
- pv/localStaticLock.h
|
- pv/localStaticLock.h
|
||||||
- pv/pvCopy.h (see epics::pvData::PVRequestMapper)
|
- pv/pvCopy.h (see epics::pvData::PVRequestMapper)
|
||||||
- Removals
|
- Removals
|
||||||
- Remove previously deprecated executor.h, queue.h and timerFunction.h
|
- Remove previously deprecated executor.h, queue.h and timerFunction.h
|
||||||
- Remove *HashFunction functors to "hash" Field sub-classes which were never fully implemented.
|
- Remove *HashFunction functors to "hash" Field sub-classes which were never fully implemented.
|
||||||
- Fixes
|
- Fixes
|
||||||
- Make thread safe getFieldCreate() and getPVDataCreate()
|
- Make thread safe getFieldCreate() and getPVDataCreate()
|
||||||
- Workaround for MSVC pickyness that iterators be non-NULL, even when not de-referenced.
|
- Workaround for MSVC pickyness that iterators be non-NULL, even when not de-referenced.
|
||||||
- Fix alignment fault during (de)serialization on RTEMS/vxWorks.
|
- Fix alignment fault during (de)serialization on RTEMS/vxWorks.
|
||||||
- Fix epics::pvData::shared_vector::swap() for void specialization.
|
- Fix epics::pvData::shared_vector::swap() for void specialization.
|
||||||
- Changes in several epics::pvData::Field sub-classes to return const ref. instead of a copy.
|
- Changes in several epics::pvData::Field sub-classes to return const ref. instead of a copy.
|
||||||
- Additions
|
- Additions
|
||||||
- epics::pvData::shared_vector add c++11 move and construct for initializer list.
|
- epics::pvData::shared_vector add c++11 move and construct for initializer list.
|
||||||
- Add epics::pvData::AnyScalar::clear()
|
- Add epics::pvData::AnyScalar::clear()
|
||||||
- Add ctor epics::pvData::AnyScalar(ScalarType, const void*) to allow construction from an untyped buffer.
|
- Add ctor epics::pvData::AnyScalar(ScalarType, const void*) to allow construction from an untyped buffer.
|
||||||
- Add epics::pvData::Timer::close()
|
- Add epics::pvData::Timer::close()
|
||||||
- Allow epics::pvData::castUnsafe() from const char* without first allocating a std::string.
|
- Allow epics::pvData::castUnsafe() from const char* without first allocating a std::string.
|
||||||
- De-duplication of epics::pvData::Field instances is performed using a global hash table.
|
- De-duplication of epics::pvData::Field instances is performed using a global hash table.
|
||||||
Identical definitions will share a single instance. Allows O(0) comparision.
|
Identical definitions will share a single instance. Allows O(0) comparision.
|
||||||
- Add epics::pvData::PVRequestMapper to facilitate (partial) copying between PVStructure instances
|
- Add epics::pvData::PVRequestMapper to facilitate (partial) copying between PVStructure instances
|
||||||
modified by a pvRequest.
|
modified by a pvRequest.
|
||||||
- Add shorthand notations epics::pvData::FieldBuilder::begin() and epics::pvData::Field::build()
|
- Add shorthand notations epics::pvData::FieldBuilder::begin() and epics::pvData::Field::build()
|
||||||
|
|
||||||
Release 7.0.0 (Dec 2017)
|
Release 7.0.0 (Dec 2017)
|
||||||
========================
|
========================
|
||||||
|
|
||||||
- Removals
|
- Removals
|
||||||
- Remove requester.h, monitor.h, and destroyable.h.. Migrated to the pvAccessCPP module.
|
- Remove requester.h, monitor.h, and destroyable.h.. Migrated to the pvAccessCPP module.
|
||||||
- Previously deprecated monitorPlugin.h is removed.
|
- Previously deprecated monitorPlugin.h is removed.
|
||||||
- Remove pv/messageQueue.h and epics::pvData::MessageQueue
|
- Remove pv/messageQueue.h and epics::pvData::MessageQueue
|
||||||
- Deprecate the following utility classes, to be removed in 8.0.
|
- Deprecate the following utility classes, to be removed in 8.0.
|
||||||
- epics::pvData::Queue
|
- epics::pvData::Queue
|
||||||
- epics::pvData::Executor
|
- epics::pvData::Executor
|
||||||
- epics::pvData::TimeFunction
|
- epics::pvData::TimeFunction
|
||||||
- Additions
|
- Additions
|
||||||
- Add pv/pvdVersion.h which is included by pv/pvIntrospect.h
|
- Add pv/pvdVersion.h which is included by pv/pvIntrospect.h
|
||||||
- Add epics::pvData::createRequest() function. Alternative to epics::pvData::CreateRequest class which throws on error.
|
- Add epics::pvData::createRequest() function. Alternative to epics::pvData::CreateRequest class which throws on error.
|
||||||
- epics::pvData::FieldBuilder allow Structure defintion to be changed/appended
|
- epics::pvData::FieldBuilder allow Structure defintion to be changed/appended
|
||||||
- Add epics::pvData::ValueBuilder like FieldBuilder also sets initial values.
|
- Add epics::pvData::ValueBuilder like FieldBuilder also sets initial values.
|
||||||
- Can also be constructed using an existing PVStructure to allow "editing".
|
- Can also be constructed using an existing PVStructure to allow "editing".
|
||||||
- Add debugPtr.h wrapper with reference tracking to assist in troubleshooting shared_ptr related ref. loops.
|
- Add debugPtr.h wrapper with reference tracking to assist in troubleshooting shared_ptr related ref. loops.
|
||||||
- Add @ref pvjson utilities
|
- Add @ref pvjson utilities
|
||||||
- Add reftrack @ref pvd_reftrack
|
- Add reftrack @ref pvd_reftrack
|
||||||
- Add header typemap.h to facilitate boilerplate switch() over ScalarType
|
- Add header typemap.h to facilitate boilerplate switch() over ScalarType
|
||||||
- Add epics::auto_ptr typedef in help writing code supporting both c++98 and c++11 w/o copious deprecation warnings.
|
- Add epics::auto_ptr typedef in help writing code supporting both c++98 and c++11 w/o copious deprecation warnings.
|
||||||
|
|
||||||
|
|
||||||
Release 6.0.1
|
Release 6.0.1
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ struct CreateRequestImpl {
|
|||||||
if(pos==string::npos) break;
|
if(pos==string::npos) break;
|
||||||
numValues++;
|
numValues++;
|
||||||
index = pos +1;
|
index = pos +1;
|
||||||
}
|
}
|
||||||
vector<string> valueList(numValues,"");
|
vector<string> valueList(numValues,"");
|
||||||
index=0;
|
index=0;
|
||||||
for(size_t i=0; i<numValues; i++) {
|
for(size_t i=0; i<numValues; i++) {
|
||||||
@@ -483,4 +483,3 @@ PVStructure::shared_pointer createRequest(std::string const & request)
|
|||||||
|
|
||||||
|
|
||||||
}} // namespace
|
}} // namespace
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ bool compare(const Structure& a, const Structure& b)
|
|||||||
if(&a==&b)
|
if(&a==&b)
|
||||||
return true;
|
return true;
|
||||||
if (a.getID()!=b.getID())
|
if (a.getID()!=b.getID())
|
||||||
return false;
|
return false;
|
||||||
size_t nflds=a.getNumberFields();
|
size_t nflds=a.getNumberFields();
|
||||||
if (b.getNumberFields()!=nflds)
|
if (b.getNumberFields()!=nflds)
|
||||||
return false;
|
return false;
|
||||||
@@ -111,7 +111,7 @@ bool compare(const Union& a, const Union& b)
|
|||||||
if(&a==&b)
|
if(&a==&b)
|
||||||
return true;
|
return true;
|
||||||
if (a.getID()!=b.getID())
|
if (a.getID()!=b.getID())
|
||||||
return false;
|
return false;
|
||||||
size_t nflds=a.getNumberFields();
|
size_t nflds=a.getNumberFields();
|
||||||
if (b.getNumberFields()!=nflds)
|
if (b.getNumberFields()!=nflds)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ using std::string;
|
|||||||
namespace epics { namespace pvData {
|
namespace epics { namespace pvData {
|
||||||
|
|
||||||
|
|
||||||
static std::vector<string> split(string commaSeparatedList) {
|
static std::vector<string> split(const string& commaSeparatedList) {
|
||||||
string::size_type numValues = 1;
|
string::size_type numValues = 1;
|
||||||
string::size_type index=0;
|
string::size_type index=0;
|
||||||
while(true) {
|
while(true) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include <epicsString.h>
|
#include <epicsString.h>
|
||||||
|
#include <epicsStdio.h>
|
||||||
#include <epicsMutex.h>
|
#include <epicsMutex.h>
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
|
|
||||||
@@ -87,7 +88,11 @@ Field::Field(Type type)
|
|||||||
|
|
||||||
Field::~Field() {
|
Field::~Field() {
|
||||||
REFTRACE_DECREMENT(num_instances);
|
REFTRACE_DECREMENT(num_instances);
|
||||||
FieldCreatePtr create(getFieldCreate());
|
}
|
||||||
|
|
||||||
|
void Field::cacheCleanup()
|
||||||
|
{
|
||||||
|
const FieldCreatePtr& create(getFieldCreate());
|
||||||
|
|
||||||
Lock G(create->mutex);
|
Lock G(create->mutex);
|
||||||
|
|
||||||
@@ -109,7 +114,7 @@ std::tr1::shared_ptr<PVField> Field::build() const
|
|||||||
|
|
||||||
std::ostream& operator<<(std::ostream& o, const Field& f)
|
std::ostream& operator<<(std::ostream& o, const Field& f)
|
||||||
{
|
{
|
||||||
return f.dump(o);
|
return f.dump(o);
|
||||||
};
|
};
|
||||||
|
|
||||||
Scalar::Scalar(ScalarType scalarType)
|
Scalar::Scalar(ScalarType scalarType)
|
||||||
@@ -119,7 +124,10 @@ Scalar::Scalar(ScalarType scalarType)
|
|||||||
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Scalar from invalid ScalarType");
|
THROW_EXCEPTION2(std::invalid_argument, "Can't construct Scalar from invalid ScalarType");
|
||||||
}
|
}
|
||||||
|
|
||||||
Scalar::~Scalar(){}
|
Scalar::~Scalar()
|
||||||
|
{
|
||||||
|
cacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& Scalar::dump(std::ostream& o) const
|
std::ostream& Scalar::dump(std::ostream& o) const
|
||||||
{
|
{
|
||||||
@@ -129,18 +137,18 @@ std::ostream& Scalar::dump(std::ostream& o) const
|
|||||||
string Scalar::getID() const
|
string Scalar::getID() const
|
||||||
{
|
{
|
||||||
static const string idScalarLUT[] = {
|
static const string idScalarLUT[] = {
|
||||||
"boolean", // pvBoolean
|
"boolean", // pvBoolean
|
||||||
"byte", // pvByte
|
"byte", // pvByte
|
||||||
"short", // pvShort
|
"short", // pvShort
|
||||||
"int", // pvInt
|
"int", // pvInt
|
||||||
"long", // pvLong
|
"long", // pvLong
|
||||||
"ubyte", // pvUByte
|
"ubyte", // pvUByte
|
||||||
"ushort", // pvUShort
|
"ushort", // pvUShort
|
||||||
"uint", // pvUInt
|
"uint", // pvUInt
|
||||||
"ulong", // pvULong
|
"ulong", // pvULong
|
||||||
"float", // pvFloat
|
"float", // pvFloat
|
||||||
"double", // pvDouble
|
"double", // pvDouble
|
||||||
"string" // pvString
|
"string" // pvString
|
||||||
};
|
};
|
||||||
return idScalarLUT[scalarType];
|
return idScalarLUT[scalarType];
|
||||||
}
|
}
|
||||||
@@ -209,20 +217,21 @@ BoundedString::BoundedString(std::size_t maxStringLength) :
|
|||||||
THROW_EXCEPTION2(std::invalid_argument, "maxLength == 0");
|
THROW_EXCEPTION2(std::invalid_argument, "maxLength == 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundedString::~BoundedString() {}
|
BoundedString::~BoundedString()
|
||||||
|
{
|
||||||
|
cacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static string emptyStringtring;
|
|
||||||
|
|
||||||
static void serializeStructureField(const Structure* structure, ByteBuffer* buffer, SerializableControl* control)
|
static void serializeStructureField(const Structure* structure, ByteBuffer* buffer, SerializableControl* control)
|
||||||
{
|
{
|
||||||
// to optimize default (non-empty) IDs optimization
|
// to optimize default (non-empty) IDs optimization
|
||||||
// empty IDs are not allowed
|
// empty IDs are not allowed
|
||||||
string id = structure->getID();
|
string id = structure->getID();
|
||||||
if (id == Structure::DEFAULT_ID) // TODO slow comparison
|
if (id == Structure::DEFAULT_ID) // TODO slow comparison
|
||||||
SerializeHelper::serializeString(emptyStringtring, buffer, control);
|
SerializeHelper::serializeString(string(), buffer, control);
|
||||||
else
|
else
|
||||||
SerializeHelper::serializeString(id, buffer, control);
|
SerializeHelper::serializeString(id, buffer, control);
|
||||||
|
|
||||||
FieldConstPtrArray const & fields = structure->getFields();
|
FieldConstPtrArray const & fields = structure->getFields();
|
||||||
StringArray const & fieldNames = structure->getFieldNames();
|
StringArray const & fieldNames = structure->getFieldNames();
|
||||||
@@ -250,18 +259,18 @@ static StructureConstPtr deserializeStructureField(const FieldCreate* fieldCreat
|
|||||||
if (id.empty())
|
if (id.empty())
|
||||||
return fieldCreate->createStructure(fieldNames, fields);
|
return fieldCreate->createStructure(fieldNames, fields);
|
||||||
else
|
else
|
||||||
return fieldCreate->createStructure(id, fieldNames, fields);
|
return fieldCreate->createStructure(id, fieldNames, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serializeUnionField(const Union* punion, ByteBuffer* buffer, SerializableControl* control)
|
static void serializeUnionField(const Union* punion, ByteBuffer* buffer, SerializableControl* control)
|
||||||
{
|
{
|
||||||
// to optimize default (non-empty) IDs optimization
|
// to optimize default (non-empty) IDs optimization
|
||||||
// empty IDs are not allowed
|
// empty IDs are not allowed
|
||||||
string id = punion->getID();
|
string id = punion->getID();
|
||||||
if (id == Union::DEFAULT_ID) // TODO slow comparison
|
if (id == Union::DEFAULT_ID) // TODO slow comparison
|
||||||
SerializeHelper::serializeString(emptyStringtring, buffer, control);
|
SerializeHelper::serializeString(string(), buffer, control);
|
||||||
else
|
else
|
||||||
SerializeHelper::serializeString(id, buffer, control);
|
SerializeHelper::serializeString(id, buffer, control);
|
||||||
|
|
||||||
FieldConstPtrArray const & fields = punion->getFields();
|
FieldConstPtrArray const & fields = punion->getFields();
|
||||||
StringArray const & fieldNames = punion->getFieldNames();
|
StringArray const & fieldNames = punion->getFieldNames();
|
||||||
@@ -289,7 +298,7 @@ static UnionConstPtr deserializeUnionField(const FieldCreate* fieldCreate, ByteB
|
|||||||
if (id.empty())
|
if (id.empty())
|
||||||
return fieldCreate->createUnion(fieldNames, fields);
|
return fieldCreate->createUnion(fieldNames, fields);
|
||||||
else
|
else
|
||||||
return fieldCreate->createUnion(id, fieldNames, fields);
|
return fieldCreate->createUnion(id, fieldNames, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array::Array(Type type)
|
Array::Array(Type type)
|
||||||
@@ -307,23 +316,26 @@ ScalarArray::ScalarArray(ScalarType elementType)
|
|||||||
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
|
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
|
||||||
}
|
}
|
||||||
|
|
||||||
ScalarArray::~ScalarArray() {}
|
ScalarArray::~ScalarArray()
|
||||||
|
{
|
||||||
|
cacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
const string ScalarArray::getIDScalarArrayLUT() const
|
const string ScalarArray::getIDScalarArrayLUT() const
|
||||||
{
|
{
|
||||||
static const string idScalarArrayLUT[] = {
|
static const string idScalarArrayLUT[] = {
|
||||||
"boolean[]", // pvBoolean
|
"boolean[]", // pvBoolean
|
||||||
"byte[]", // pvByte
|
"byte[]", // pvByte
|
||||||
"short[]", // pvShort
|
"short[]", // pvShort
|
||||||
"int[]", // pvInt
|
"int[]", // pvInt
|
||||||
"long[]", // pvLong
|
"long[]", // pvLong
|
||||||
"ubyte[]", // pvUByte
|
"ubyte[]", // pvUByte
|
||||||
"ushort[]", // pvUShort
|
"ushort[]", // pvUShort
|
||||||
"uint[]", // pvUInt
|
"uint[]", // pvUInt
|
||||||
"ulong[]", // pvULong
|
"ulong[]", // pvULong
|
||||||
"float[]", // pvFloat
|
"float[]", // pvFloat
|
||||||
"double[]", // pvDouble
|
"double[]", // pvDouble
|
||||||
"string[]" // pvString
|
"string[]" // pvString
|
||||||
};
|
};
|
||||||
return idScalarArrayLUT[elementType];
|
return idScalarArrayLUT[elementType];
|
||||||
}
|
}
|
||||||
@@ -353,7 +365,10 @@ std::tr1::shared_ptr<PVScalarArray> ScalarArray::build() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BoundedScalarArray::~BoundedScalarArray() {}
|
BoundedScalarArray::~BoundedScalarArray()
|
||||||
|
{
|
||||||
|
cacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
BoundedScalarArray::BoundedScalarArray(ScalarType elementType, size_t size)
|
BoundedScalarArray::BoundedScalarArray(ScalarType elementType, size_t size)
|
||||||
: ScalarArray(elementType),
|
: ScalarArray(elementType),
|
||||||
@@ -364,7 +379,8 @@ BoundedScalarArray::BoundedScalarArray(ScalarType elementType, size_t size)
|
|||||||
string BoundedScalarArray::getID() const
|
string BoundedScalarArray::getID() const
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "%s<%zu>", ScalarTypeFunc::name(getElementType()), size);
|
epicsSnprintf(buffer, sizeof(buffer), "%s<%lu>",
|
||||||
|
ScalarTypeFunc::name(getElementType()), (unsigned long) size);
|
||||||
return string(buffer);
|
return string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,7 +391,10 @@ void BoundedScalarArray::serialize(ByteBuffer *buffer, SerializableControl *cont
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FixedScalarArray::~FixedScalarArray() {}
|
FixedScalarArray::~FixedScalarArray()
|
||||||
|
{
|
||||||
|
cacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
FixedScalarArray::FixedScalarArray(ScalarType elementType, size_t size)
|
FixedScalarArray::FixedScalarArray(ScalarType elementType, size_t size)
|
||||||
: ScalarArray(elementType),
|
: ScalarArray(elementType),
|
||||||
@@ -386,7 +405,8 @@ FixedScalarArray::FixedScalarArray(ScalarType elementType, size_t size)
|
|||||||
string FixedScalarArray::getID() const
|
string FixedScalarArray::getID() const
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
sprintf(buffer, "%s[%zu]", ScalarTypeFunc::name(getElementType()), size);
|
epicsSnprintf(buffer, sizeof(buffer), "%s[%lu]",
|
||||||
|
ScalarTypeFunc::name(getElementType()), (unsigned long) size);
|
||||||
return string(buffer);
|
return string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,11 +423,14 @@ StructureArray::StructureArray(StructureConstPtr const & structure)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
StructureArray::~StructureArray() {}
|
StructureArray::~StructureArray()
|
||||||
|
{
|
||||||
|
cacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
string StructureArray::getID() const
|
string StructureArray::getID() const
|
||||||
{
|
{
|
||||||
return pstructure->getID() + "[]";
|
return pstructure->getID() + "[]";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& StructureArray::dump(std::ostream& o) const
|
std::ostream& StructureArray::dump(std::ostream& o) const
|
||||||
@@ -440,11 +463,14 @@ UnionArray::UnionArray(UnionConstPtr const & _punion)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
UnionArray::~UnionArray() {}
|
UnionArray::~UnionArray()
|
||||||
|
{
|
||||||
|
cacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
string UnionArray::getID() const
|
string UnionArray::getID() const
|
||||||
{
|
{
|
||||||
return punion->getID() + "[]";
|
return punion->getID() + "[]";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& UnionArray::dump(std::ostream& o) const
|
std::ostream& UnionArray::dump(std::ostream& o) const
|
||||||
@@ -524,12 +550,15 @@ Structure::Structure (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Structure::~Structure() { }
|
Structure::~Structure()
|
||||||
|
{
|
||||||
|
cacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
string Structure::getID() const
|
string Structure::getID() const
|
||||||
{
|
{
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldConstPtr Structure::getField(string const & fieldName) const {
|
FieldConstPtr Structure::getField(string const & fieldName) const {
|
||||||
@@ -702,7 +731,10 @@ Union::Union (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Union::~Union() { }
|
Union::~Union()
|
||||||
|
{
|
||||||
|
cacheCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
int32 Union::guess(Type t, ScalarType s) const
|
int32 Union::guess(Type t, ScalarType s) const
|
||||||
{
|
{
|
||||||
@@ -742,7 +774,7 @@ int32 Union::guess(Type t, ScalarType s) const
|
|||||||
|
|
||||||
string Union::getID() const
|
string Union::getID() const
|
||||||
{
|
{
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldConstPtr Union::getField(string const & fieldName) const {
|
FieldConstPtr Union::getField(string const & fieldName) const {
|
||||||
@@ -937,7 +969,7 @@ FieldBuilder::FieldBuilder(const FieldBuilderPtr & _parentBuilder,
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
FieldBuilder::FieldBuilder(FieldBuilderPtr const & _parentBuilder,
|
FieldBuilder::FieldBuilder(FieldBuilderPtr const & _parentBuilder,
|
||||||
string const & _nestedName,
|
string const & _nestedName,
|
||||||
Type _nestedClassToBuild, bool _nestedArray)
|
Type _nestedClassToBuild, bool _nestedArray)
|
||||||
:fieldCreate(_parentBuilder->fieldCreate)
|
:fieldCreate(_parentBuilder->fieldCreate)
|
||||||
,idSet(false)
|
,idSet(false)
|
||||||
@@ -950,10 +982,10 @@ FieldBuilder::FieldBuilder(FieldBuilderPtr const & _parentBuilder,
|
|||||||
|
|
||||||
void FieldBuilder::reset()
|
void FieldBuilder::reset()
|
||||||
{
|
{
|
||||||
id.erase();
|
id.erase();
|
||||||
idSet = false;
|
idSet = false;
|
||||||
fieldNames.clear();
|
fieldNames.clear();
|
||||||
fields.clear();
|
fields.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldBuilderPtr FieldBuilder::begin()
|
FieldBuilderPtr FieldBuilder::begin()
|
||||||
@@ -994,7 +1026,7 @@ FieldBuilderPtr FieldBuilder::add(string const & name, FieldConstPtr const & fie
|
|||||||
} else if(*cur!=*field) {
|
} else if(*cur!=*field) {
|
||||||
THROW_EXCEPTION2(std::runtime_error, "duplicate field name w/ different type : "+name);
|
THROW_EXCEPTION2(std::runtime_error, "duplicate field name w/ different type : "+name);
|
||||||
} // else exact duplicate is silently ignored
|
} // else exact duplicate is silently ignored
|
||||||
return shared_from_this();
|
return shared_from_this();
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldBuilderPtr FieldBuilder::addArray(string const & name, ScalarType scalarType)
|
FieldBuilderPtr FieldBuilder::addArray(string const & name, ScalarType scalarType)
|
||||||
@@ -1626,4 +1658,3 @@ namespace std{
|
|||||||
return o << "nullptr";
|
return o << "nullptr";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ PVArray::PVArray(FieldConstPtr const & field)
|
|||||||
|
|
||||||
std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array)
|
std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array)
|
||||||
{
|
{
|
||||||
return array.dumpValue(manip.stream, manip.index);
|
return array.dumpValue(manip.stream, manip.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -144,8 +144,7 @@ PVString::PVString(ScalarConstPtr const & scalar)
|
|||||||
|
|
||||||
std::ostream& PVString::dumpValue(std::ostream& o) const
|
std::ostream& PVString::dumpValue(std::ostream& o) const
|
||||||
{
|
{
|
||||||
// we escape, but do not quote, for scalar string
|
o<<maybeQuote(get());
|
||||||
o<<escape(get());
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,17 +159,17 @@ void PVString::serialize(ByteBuffer *pbuffer,
|
|||||||
void PVString::serialize(ByteBuffer *pbuffer,
|
void PVString::serialize(ByteBuffer *pbuffer,
|
||||||
SerializableControl *pflusher, size_t offset, size_t count) const
|
SerializableControl *pflusher, size_t offset, size_t count) const
|
||||||
{
|
{
|
||||||
// check bounds
|
// check bounds
|
||||||
const size_t length = storage.value.length();
|
const size_t length = storage.value.length();
|
||||||
/*if (offset < 0) offset = 0;
|
/*if (offset < 0) offset = 0;
|
||||||
else*/ if (offset > length) offset = length;
|
else*/ if (offset > length) offset = length;
|
||||||
//if (count < 0) count = length;
|
//if (count < 0) count = length;
|
||||||
|
|
||||||
const size_t maxCount = length - offset;
|
const size_t maxCount = length - offset;
|
||||||
if (count > maxCount)
|
if (count > maxCount)
|
||||||
count = maxCount;
|
count = maxCount;
|
||||||
|
|
||||||
// write
|
// write
|
||||||
SerializeHelper::serializeSubstring(storage.value, offset, count, pbuffer, pflusher);
|
SerializeHelper::serializeSubstring(storage.value, offset, count, pbuffer, pflusher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +232,7 @@ std::ostream& PVValueArray<T>::dumpValue(std::ostream& o) const
|
|||||||
template<>
|
template<>
|
||||||
std::ostream& PVValueArray<std::string>::dumpValue(std::ostream& o, size_t index) const
|
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<>
|
template<>
|
||||||
@@ -244,9 +243,9 @@ std::ostream& PVValueArray<std::string>::dumpValue(std::ostream& o) const
|
|||||||
end(v.end());
|
end(v.end());
|
||||||
o << '[';
|
o << '[';
|
||||||
if(it!=end) {
|
if(it!=end) {
|
||||||
o << '"' << escape(*it++) << '"';
|
o << maybeQuote(*it++);
|
||||||
for(; it!=end; ++it)
|
for(; it!=end; ++it)
|
||||||
o << ", \"" << escape(*it) << '"';
|
o << ", " << maybeQuote(*it);
|
||||||
|
|
||||||
}
|
}
|
||||||
return o << ']';
|
return o << ']';
|
||||||
@@ -780,4 +779,3 @@ namespace std{
|
|||||||
return o << "nullptr";
|
return o << "nullptr";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ bool PVField::equals(PVField &pv)
|
|||||||
|
|
||||||
std::ostream& operator<<(std::ostream& o, const PVField& f)
|
std::ostream& operator<<(std::ostream& o, const PVField& f)
|
||||||
{
|
{
|
||||||
return f.dumpValue(o);
|
return f.dumpValue(o);
|
||||||
};
|
};
|
||||||
|
|
||||||
string PVField::getFullName() const
|
string PVField::getFullName() const
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ PVStructure::PVStructure(StructureConstPtr const & structurePtr)
|
|||||||
pvFields.push_back(pvDataCreate->createPVField(fields[i]));
|
pvFields.push_back(pvDataCreate->createPVField(fields[i]));
|
||||||
}
|
}
|
||||||
for(size_t i=0; i<numberFields; i++) {
|
for(size_t i=0; i<numberFields; i++) {
|
||||||
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
pvFields[i]->setParentAndName(this,fieldNames[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,22 +307,22 @@ std::ostream& PVStructure::dumpValue(std::ostream& o) const
|
|||||||
o << format::indent() << getStructure()->getID() << ' ' << getFieldName();
|
o << format::indent() << getStructure()->getID() << ' ' << getFieldName();
|
||||||
o << std::endl;
|
o << std::endl;
|
||||||
{
|
{
|
||||||
format::indent_scope s(o);
|
format::indent_scope s(o);
|
||||||
|
|
||||||
PVFieldPtrArray const & fieldsData = getPVFields();
|
PVFieldPtrArray const & fieldsData = getPVFields();
|
||||||
if (fieldsData.size() != 0) {
|
if (fieldsData.size() != 0) {
|
||||||
size_t length = getStructure()->getNumberFields();
|
size_t length = getStructure()->getNumberFields();
|
||||||
for(size_t i=0; i<length; i++) {
|
for(size_t i=0; i<length; i++) {
|
||||||
PVFieldPtr fieldField = fieldsData[i];
|
PVFieldPtr fieldField = fieldsData[i];
|
||||||
Type type = fieldField->getField()->getType();
|
Type type = fieldField->getField()->getType();
|
||||||
if (type == scalar || type == scalarArray)
|
if (type == scalar || type == scalarArray)
|
||||||
o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
|
o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
|
||||||
else
|
else
|
||||||
o << *(fieldField.get());
|
o << *(fieldField.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -218,10 +218,10 @@ std::ostream& PVStructureArray::dumpValue(std::ostream& o) const
|
|||||||
size_t length = getLength();
|
size_t length = getLength();
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
{
|
{
|
||||||
format::indent_scope s(o);
|
format::indent_scope s(o);
|
||||||
|
|
||||||
for (size_t i = 0; i < length; i++)
|
for (size_t i = 0; i < length; i++)
|
||||||
dumpValue(o, i);
|
dumpValue(o, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
|
|||||||
@@ -79,9 +79,9 @@ PVFieldPtr PVUnion::select(int32 index)
|
|||||||
PVFieldPtr PVUnion::select(string const & fieldName)
|
PVFieldPtr PVUnion::select(string const & fieldName)
|
||||||
{
|
{
|
||||||
int32 index = variant ? -1 : static_cast<int32>(unionPtr->getFieldIndex(fieldName));
|
int32 index = variant ? -1 : static_cast<int32>(unionPtr->getFieldIndex(fieldName));
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
throw std::invalid_argument("no such fieldName");
|
throw std::invalid_argument("no such fieldName");
|
||||||
return select(index);
|
return select(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PVUnion::set(int32 index, PVFieldPtr const & value)
|
void PVUnion::set(int32 index, PVFieldPtr const & value)
|
||||||
@@ -94,14 +94,14 @@ void PVUnion::set(int32 index, PVFieldPtr const & value)
|
|||||||
{
|
{
|
||||||
// for undefined index we accept only null values
|
// for undefined index we accept only null values
|
||||||
if (value)
|
if (value)
|
||||||
throw std::invalid_argument("non-null value for index == UNDEFINED_INDEX");
|
throw std::invalid_argument("non-null value for index == UNDEFINED_INDEX");
|
||||||
}
|
}
|
||||||
else if (index < 0 || size_t(index) >= unionPtr->getFields().size())
|
else if (index < 0 || size_t(index) >= unionPtr->getFields().size())
|
||||||
throw std::invalid_argument("index out of bounds");
|
throw std::invalid_argument("index out of bounds");
|
||||||
else if (!value)
|
else if (!value)
|
||||||
throw std::invalid_argument("Can't set defined index w/ NULL");
|
throw std::invalid_argument("Can't set defined index w/ NULL");
|
||||||
else if (value->getField() != unionPtr->getField(index))
|
else if (value->getField() != unionPtr->getField(index))
|
||||||
throw std::invalid_argument("selected field and its introspection data do not match");
|
throw std::invalid_argument("selected field and its introspection data do not match");
|
||||||
}
|
}
|
||||||
|
|
||||||
selector = index;
|
selector = index;
|
||||||
@@ -180,20 +180,20 @@ std::ostream& PVUnion::dumpValue(std::ostream& o) const
|
|||||||
{
|
{
|
||||||
o << format::indent() << getUnion()->getID() << ' ' << getFieldName() << std::endl;
|
o << format::indent() << getUnion()->getID() << ' ' << getFieldName() << std::endl;
|
||||||
{
|
{
|
||||||
format::indent_scope s(o);
|
format::indent_scope s(o);
|
||||||
const PVField::const_shared_pointer& fieldField = get();
|
const PVField::const_shared_pointer& fieldField = get();
|
||||||
if (fieldField.get() == NULL)
|
if (fieldField.get() == NULL)
|
||||||
o << format::indent() << "(none)" << std::endl;
|
o << format::indent() << "(none)" << std::endl;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Type type = fieldField->getField()->getType();
|
Type type = fieldField->getField()->getType();
|
||||||
if (type == scalar || type == scalarArray)
|
if (type == scalar || type == scalarArray)
|
||||||
o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
|
o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
|
||||||
else
|
else
|
||||||
o << *(fieldField.get());
|
o << *(fieldField.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PVUnion::copy(const PVUnion& from)
|
void PVUnion::copy(const PVUnion& from)
|
||||||
|
|||||||
@@ -217,10 +217,10 @@ std::ostream& PVUnionArray::dumpValue(std::ostream& o) const
|
|||||||
size_t length = getLength();
|
size_t length = getLength();
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
{
|
{
|
||||||
format::indent_scope s(o);
|
format::indent_scope s(o);
|
||||||
|
|
||||||
for (size_t i = 0; i < length; i++)
|
for (size_t i = 0; i < length; i++)
|
||||||
dumpValue(o, i);
|
dumpValue(o, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
|
|||||||
@@ -123,8 +123,8 @@ StructureConstPtr StandardField::createProperties(string id,FieldConstPtr field,
|
|||||||
while(gotValueAlarm) {
|
while(gotValueAlarm) {
|
||||||
if(type==epics::pvData::scalar || type==epics::pvData::scalarArray) {
|
if(type==epics::pvData::scalar || type==epics::pvData::scalarArray) {
|
||||||
ScalarType scalarType = (type==epics::pvData::scalar) ?
|
ScalarType scalarType = (type==epics::pvData::scalar) ?
|
||||||
static_pointer_cast<const Scalar>(field)->getScalarType() :
|
static_pointer_cast<const Scalar>(field)->getScalarType() :
|
||||||
static_pointer_cast<const ScalarArray>(field)->getElementType();
|
static_pointer_cast<const ScalarArray>(field)->getElementType();
|
||||||
switch(scalarType) {
|
switch(scalarType) {
|
||||||
case pvBoolean: valueAlarm = booleanAlarmField; break;
|
case pvBoolean: valueAlarm = booleanAlarmField; break;
|
||||||
case pvByte: valueAlarm = byteAlarmField; break;
|
case pvByte: valueAlarm = byteAlarmField; break;
|
||||||
|
|||||||
@@ -19,9 +19,7 @@
|
|||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/bitSet.h>
|
#include <pv/bitSet.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
#include <pv/json.h>
|
||||||
# include <pv/json.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace epics { namespace pvData {
|
namespace epics { namespace pvData {
|
||||||
|
|
||||||
@@ -173,7 +171,7 @@ bool printEnumT(std::ostream& strm, const PVStructure& top, bool fromtop)
|
|||||||
if(I>=ch.size()) {
|
if(I>=ch.size()) {
|
||||||
strm<<" <undefined>";
|
strm<<" <undefined>";
|
||||||
} else {
|
} else {
|
||||||
strm<<' '<<escape(ch[I]);
|
strm<<' '<<maybeQuote(ch[I]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -182,7 +180,7 @@ void csvEscape(std::string& S)
|
|||||||
{
|
{
|
||||||
// concise, not particularly efficient...
|
// concise, not particularly efficient...
|
||||||
std::string temp(escape(S).style(escape::CSV).str());
|
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;
|
std::string temp2;
|
||||||
temp2.reserve(temp.size()+2);
|
temp2.reserve(temp.size()+2);
|
||||||
temp2.push_back('\"');
|
temp2.push_back('\"');
|
||||||
@@ -190,7 +188,7 @@ void csvEscape(std::string& S)
|
|||||||
temp2.push_back('\"');
|
temp2.push_back('\"');
|
||||||
temp2.swap(temp);
|
temp2.swap(temp);
|
||||||
}
|
}
|
||||||
S = temp;
|
S.swap(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool printTable(std::ostream& strm, const PVStructure& top)
|
bool printTable(std::ostream& strm, const PVStructure& top)
|
||||||
@@ -404,15 +402,14 @@ void printRaw(std::ostream& strm, const PVStructure::Formatter& format, const PV
|
|||||||
std::ostream& operator<<(std::ostream& strm, const PVStructure::Formatter& format)
|
std::ostream& operator<<(std::ostream& strm, const PVStructure::Formatter& format)
|
||||||
{
|
{
|
||||||
if(format.xfmt==PVStructure::Formatter::JSON) {
|
if(format.xfmt==PVStructure::Formatter::JSON) {
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
|
||||||
JSONPrintOptions opts;
|
JSONPrintOptions opts;
|
||||||
opts.multiLine = false;
|
opts.multiLine = false;
|
||||||
|
#if EPICS_VERSION_INT>=VERSION_INT(7,0,6,1)
|
||||||
|
opts.json5 = true;
|
||||||
|
#endif
|
||||||
printJSON(strm, format.xtop, format.xshow ? *format.xshow : BitSet().set(0), opts);
|
printJSON(strm, format.xtop, format.xshow ? *format.xshow : BitSet().set(0), opts);
|
||||||
strm<<'\n';
|
strm<<'\n';
|
||||||
return strm;
|
return strm;
|
||||||
#else
|
|
||||||
// fall through to Raw
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else if(format.xfmt==PVStructure::Formatter::NT) {
|
} else if(format.xfmt==PVStructure::Formatter::NT) {
|
||||||
std::string id(format.xtop.getStructure()->getID()),
|
std::string id(format.xtop.getStructure()->getID()),
|
||||||
@@ -503,7 +500,7 @@ std::ostream& operator<<(std::ostream& strm, const escape& Q)
|
|||||||
case '\'': next = '\''; break;
|
case '\'': next = '\''; break;
|
||||||
case '\"': next = '\"'; if(Q.S==escape::CSV) quote = '"'; break;
|
case '\"': next = '\"'; if(Q.S==escape::CSV) quote = '"'; break;
|
||||||
default:
|
default:
|
||||||
if(!isprint(C)) {
|
if(!isprint((unsigned char)C)) {
|
||||||
// print three charator escape
|
// print three charator escape
|
||||||
strm<<"\\x"<<hexdigit(C>>4)<<hexdigit(C);
|
strm<<"\\x"<<hexdigit(C>>4)<<hexdigit(C);
|
||||||
} else {
|
} else {
|
||||||
@@ -520,4 +517,38 @@ std::ostream& operator<<(std::ostream& strm, const escape& Q)
|
|||||||
return strm;
|
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((unsigned char)q.s[i])) {
|
||||||
|
esc = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(esc) {
|
||||||
|
strm<<'"'<<escape(q.s)<<'"';
|
||||||
|
} else {
|
||||||
|
strm<<q.s;
|
||||||
|
}
|
||||||
|
return strm;
|
||||||
|
}
|
||||||
|
|
||||||
}} //epics::pvData
|
}} //epics::pvData
|
||||||
|
|||||||
@@ -272,4 +272,3 @@ void copy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ INC += pv/json.h
|
|||||||
LIBSRCS += parsehelper.cpp
|
LIBSRCS += parsehelper.cpp
|
||||||
LIBSRCS += parseany.cpp
|
LIBSRCS += parseany.cpp
|
||||||
LIBSRCS += parseinto.cpp
|
LIBSRCS += parseinto.cpp
|
||||||
LIBSRCS += print.cpp
|
LIBSRCS += jprint.cpp
|
||||||
|
|||||||
305
src/json/jprint.cpp
Normal file
305
src/json/jprint.cpp
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* Copyright information and license terms for this software can be
|
||||||
|
* found in the file LICENSE that is included with the distribution
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <errlog.h>
|
||||||
|
#include <yajl_gen.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include <pv/pvdVersion.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/valueBuilder.h>
|
||||||
|
#include <pv/bitSet.h>
|
||||||
|
#include "pv/json.h"
|
||||||
|
|
||||||
|
namespace pvd = epics::pvData;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using namespace pvd::yajl;
|
||||||
|
|
||||||
|
void yg(yajl_gen_status sts) {
|
||||||
|
const char *msg = "<\?\?\?>";
|
||||||
|
switch(sts) {
|
||||||
|
case yajl_gen_status_ok:
|
||||||
|
case yajl_gen_generation_complete:
|
||||||
|
return;
|
||||||
|
#define CASE(STS) case STS: msg = #STS; break
|
||||||
|
CASE(yajl_gen_keys_must_be_strings);
|
||||||
|
CASE(yajl_gen_in_error_state);
|
||||||
|
CASE(yajl_gen_no_buf);
|
||||||
|
CASE(yajl_gen_invalid_number);
|
||||||
|
CASE(yajl_max_depth_exceeded);
|
||||||
|
#ifdef EPICS_YAJL_VERSION
|
||||||
|
CASE(yajl_gen_invalid_string);
|
||||||
|
#endif
|
||||||
|
#undef CASE
|
||||||
|
}
|
||||||
|
throw std::runtime_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void stream_printer(void * ctx,
|
||||||
|
const char * str,
|
||||||
|
size_arg len)
|
||||||
|
{
|
||||||
|
std::ostream *strm = (std::ostream*)ctx;
|
||||||
|
strm->write(str, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct args {
|
||||||
|
yajl_gen handle;
|
||||||
|
const pvd::JSONPrintOptions& opts;
|
||||||
|
|
||||||
|
std::string indent;
|
||||||
|
|
||||||
|
args(std::ostream& strm,
|
||||||
|
const pvd::JSONPrintOptions& opts)
|
||||||
|
:opts(opts)
|
||||||
|
,indent(opts.indent, ' ')
|
||||||
|
{
|
||||||
|
#ifndef EPICS_YAJL_VERSION
|
||||||
|
yajl_gen_config conf;
|
||||||
|
conf.beautify = opts.multiLine;
|
||||||
|
conf.indentString = indent.c_str();
|
||||||
|
if(!(handle = yajl_gen_alloc2(stream_printer, NULL, NULL, &strm)))
|
||||||
|
throw std::bad_alloc();
|
||||||
|
|
||||||
|
if(opts.json5) {
|
||||||
|
static bool warned;
|
||||||
|
if(!warned) {
|
||||||
|
warned = true;
|
||||||
|
errlogPrintf("Warning: Ignoring request to print JSON5. Update Base >= 7.0.6.1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(!(handle = yajl_gen_alloc(NULL)))
|
||||||
|
throw std::bad_alloc();
|
||||||
|
if(opts.multiLine) {
|
||||||
|
yajl_gen_config(handle, yajl_gen_beautify, 1);
|
||||||
|
yajl_gen_config(handle, yajl_gen_indent_string, indent.c_str());
|
||||||
|
} else {
|
||||||
|
yajl_gen_config(handle, yajl_gen_beautify, 0);
|
||||||
|
}
|
||||||
|
# if EPICS_VERSION_INT>=VERSION_INT(7,0,6,1)
|
||||||
|
yajl_gen_config(handle, yajl_gen_json5, (int)opts.json5);
|
||||||
|
# else
|
||||||
|
if(opts.json5) {
|
||||||
|
static bool warned;
|
||||||
|
if(!warned) {
|
||||||
|
warned = true;
|
||||||
|
errlogPrintf("Warning: Ignoring request to print JSON5. Update Base >= 7.0.6.1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
yajl_gen_config(handle, yajl_gen_print_callback, stream_printer, &strm);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
~args() {
|
||||||
|
yajl_gen_free(handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void yg_string(yajl_gen handle, const std::string& s) {
|
||||||
|
yg(yajl_gen_string(handle, (const unsigned char*)s.c_str(), s.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_field(args& A, const pvd::PVField* fld, const pvd::BitSet *mask);
|
||||||
|
|
||||||
|
void show_struct(args& A, const pvd::PVStructure* fld, const pvd::BitSet *mask)
|
||||||
|
{
|
||||||
|
const pvd::StructureConstPtr& type = fld->getStructure();
|
||||||
|
const pvd::PVFieldPtrArray& children = fld->getPVFields();
|
||||||
|
|
||||||
|
const pvd::StringArray& names = type->getFieldNames();
|
||||||
|
|
||||||
|
yg(yajl_gen_map_open(A.handle));
|
||||||
|
|
||||||
|
for(size_t i=0, N=names.size(); i<N; i++)
|
||||||
|
{
|
||||||
|
if(mask && !mask->get(children[i]->getFieldOffset())) continue;
|
||||||
|
|
||||||
|
yg_string(A.handle, names[i]);
|
||||||
|
show_field(A, children[i].get(), mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
yg(yajl_gen_map_close(A.handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_field(args& A, const pvd::PVField* fld, const pvd::BitSet *mask)
|
||||||
|
{
|
||||||
|
switch(fld->getField()->getType())
|
||||||
|
{
|
||||||
|
case pvd::scalar:
|
||||||
|
{
|
||||||
|
const pvd::PVScalar *scalar=static_cast<const pvd::PVScalar*>(fld);
|
||||||
|
switch(scalar->getScalar()->getScalarType()) {
|
||||||
|
case pvd::pvString: yg_string(A.handle, scalar->getAs<std::string>()); break;
|
||||||
|
case pvd::pvBoolean: yg(yajl_gen_bool(A.handle, scalar->getAs<pvd::boolean>())); break;
|
||||||
|
case pvd::pvDouble:
|
||||||
|
case pvd::pvFloat: yg(yajl_gen_double(A.handle, scalar->getAs<double>())); break;
|
||||||
|
// case pvd::pvULong: // can't always be exactly represented...
|
||||||
|
default:
|
||||||
|
yg(yajl_gen_integer(A.handle, scalar->getAs<pvd::int64>())); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case pvd::scalarArray:
|
||||||
|
{
|
||||||
|
const pvd::PVScalarArray *scalar=static_cast<const pvd::PVScalarArray*>(fld);
|
||||||
|
|
||||||
|
pvd::shared_vector<const void> arr;
|
||||||
|
scalar->getAs<void>(arr);
|
||||||
|
|
||||||
|
yg(yajl_gen_array_open(A.handle));
|
||||||
|
|
||||||
|
switch(arr.original_type()) {
|
||||||
|
case pvd::pvString: {
|
||||||
|
pvd::shared_vector<const std::string> sarr(pvd::shared_vector_convert<const std::string>(arr));
|
||||||
|
for(size_t i=0, N=sarr.size(); i<N; i++) {
|
||||||
|
yg_string(A.handle, sarr[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case pvd::pvBoolean: {
|
||||||
|
pvd::shared_vector<const pvd::boolean> sarr(pvd::shared_vector_convert<const pvd::boolean>(arr));
|
||||||
|
for(size_t i=0, N=sarr.size(); i<N; i++) {
|
||||||
|
yg(yajl_gen_bool(A.handle, sarr[i]));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case pvd::pvDouble:
|
||||||
|
case pvd::pvFloat: {
|
||||||
|
pvd::shared_vector<const double> sarr(pvd::shared_vector_convert<const double>(arr));
|
||||||
|
for(size_t i=0, N=sarr.size(); i<N; i++) {
|
||||||
|
yg(yajl_gen_double(A.handle, sarr[i]));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
pvd::shared_vector<const pvd::int64> sarr(pvd::shared_vector_convert<const pvd::int64>(arr));
|
||||||
|
for(size_t i=0, N=sarr.size(); i<N; i++) {
|
||||||
|
yg(yajl_gen_integer(A.handle, sarr[i]));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yg(yajl_gen_array_close(A.handle));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case pvd::structure:
|
||||||
|
show_struct(A, static_cast<const pvd::PVStructure*>(fld), mask);
|
||||||
|
return;
|
||||||
|
case pvd::structureArray:
|
||||||
|
{
|
||||||
|
pvd::PVStructureArray::const_svector arr(static_cast<const pvd::PVStructureArray*>(fld)->view());
|
||||||
|
yg(yajl_gen_array_open(A.handle));
|
||||||
|
|
||||||
|
for(size_t i=0, N=arr.size(); i<N; i++) {
|
||||||
|
if(arr[i])
|
||||||
|
show_struct(A, arr[i].get(), 0);
|
||||||
|
else
|
||||||
|
yg(yajl_gen_null(A.handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
yg(yajl_gen_array_close(A.handle));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case pvd::union_:
|
||||||
|
{
|
||||||
|
const pvd::PVUnion *U=static_cast<const pvd::PVUnion*>(fld);
|
||||||
|
const pvd::PVField::const_shared_pointer& C(U->get());
|
||||||
|
|
||||||
|
if(!C) {
|
||||||
|
yg(yajl_gen_null(A.handle));
|
||||||
|
} else {
|
||||||
|
show_field(A, C.get(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case pvd::unionArray: {
|
||||||
|
const pvd::PVUnionArray *U=static_cast<const pvd::PVUnionArray*>(fld);
|
||||||
|
pvd::PVUnionArray::const_svector arr(U->view());
|
||||||
|
|
||||||
|
yg(yajl_gen_array_open(A.handle));
|
||||||
|
|
||||||
|
for(size_t i=0, N=arr.size(); i<N; i++) {
|
||||||
|
if(arr[i])
|
||||||
|
show_field(A, arr[i].get(), 0);
|
||||||
|
else
|
||||||
|
yg(yajl_gen_null(A.handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
yg(yajl_gen_array_close(A.handle));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// should not be reached
|
||||||
|
if(A.opts.ignoreUnprintable)
|
||||||
|
yg(yajl_gen_null(A.handle));
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Encountered unprintable field type");
|
||||||
|
}
|
||||||
|
|
||||||
|
void expandBS(const pvd::PVStructure& top, pvd::BitSet& mask, bool parents) {
|
||||||
|
if(mask.get(0)) { // special handling because getSubField(0) not allowed
|
||||||
|
// wildcard
|
||||||
|
for(size_t idx=1, N=top.getNumberFields(); idx<N; idx++) {
|
||||||
|
mask.set(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for(pvd::int32 idx = mask.nextSetBit(0), N=top.getNumberFields(); idx>=0 && idx<N; idx=mask.nextSetBit(idx+1)) {
|
||||||
|
pvd::PVField::const_shared_pointer fld = top.getSubFieldT(idx);
|
||||||
|
|
||||||
|
// look forward and mark all children
|
||||||
|
for(size_t i=idx+1, N=fld->getNextFieldOffset(); i<N; i++)
|
||||||
|
mask.set(i);
|
||||||
|
|
||||||
|
if(parents) {
|
||||||
|
// look back and mark all parents
|
||||||
|
// we've already stepped past all parents so siblings will not be automatically marked
|
||||||
|
for(const pvd::PVStructure *parent = fld->getParent(); parent; parent = parent->getParent()) {
|
||||||
|
mask.set(parent->getFieldOffset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace epics{namespace pvData{
|
||||||
|
|
||||||
|
JSONPrintOptions::JSONPrintOptions()
|
||||||
|
:multiLine(true)
|
||||||
|
,ignoreUnprintable(true)
|
||||||
|
,indent(0)
|
||||||
|
,json5(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void printJSON(std::ostream& strm,
|
||||||
|
const PVStructure& val,
|
||||||
|
const BitSet& mask,
|
||||||
|
const JSONPrintOptions& opts)
|
||||||
|
{
|
||||||
|
args A(strm, opts);
|
||||||
|
pvd::BitSet emask(mask);
|
||||||
|
expandBS(val, emask, true);
|
||||||
|
if(!emask.get(0)) return;
|
||||||
|
show_struct(A, &val, &emask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printJSON(std::ostream& strm,
|
||||||
|
const PVField& val,
|
||||||
|
const JSONPrintOptions& opts)
|
||||||
|
{
|
||||||
|
args A(strm, opts);
|
||||||
|
show_field(A, &val, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // namespace epics::pvData
|
||||||
@@ -10,8 +10,6 @@
|
|||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/valueBuilder.h>
|
#include <pv/valueBuilder.h>
|
||||||
|
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
|
||||||
|
|
||||||
#include "pv/json.h"
|
#include "pv/json.h"
|
||||||
|
|
||||||
namespace pvd = epics::pvData;
|
namespace pvd = epics::pvData;
|
||||||
@@ -280,5 +278,3 @@ parseJSON(std::istream& strm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace epics::pvData
|
}} // namespace epics::pvData
|
||||||
|
|
||||||
#endif // EPICS_VERSION_INT
|
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/pvdVersion.h>
|
#include <pv/pvdVersion.h>
|
||||||
|
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
|
||||||
|
|
||||||
#include "pv/json.h"
|
#include "pv/json.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -118,5 +116,3 @@ bool yajl_parse_helper(std::istream& src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace epics::pvData
|
}} // namespace epics::pvData
|
||||||
|
|
||||||
#endif // EPICS_VERSION_INT
|
|
||||||
|
|||||||
@@ -11,9 +11,6 @@
|
|||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/valueBuilder.h>
|
#include <pv/valueBuilder.h>
|
||||||
#include <pv/bitSet.h>
|
#include <pv/bitSet.h>
|
||||||
|
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
|
||||||
|
|
||||||
#include "pv/json.h"
|
#include "pv/json.h"
|
||||||
|
|
||||||
namespace pvd = epics::pvData;
|
namespace pvd = epics::pvData;
|
||||||
@@ -347,6 +344,3 @@ void parseJSON(std::istream& strm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace epics::pvData
|
}} // namespace epics::pvData
|
||||||
|
|
||||||
#endif // EPICS_VERSION_INT
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,236 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright information and license terms for this software can be
|
|
||||||
* found in the file LICENSE that is included with the distribution
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
#include <pv/pvdVersion.h>
|
|
||||||
#include <pv/pvData.h>
|
|
||||||
#include <pv/valueBuilder.h>
|
|
||||||
#include <pv/bitSet.h>
|
|
||||||
|
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
|
||||||
|
|
||||||
#include "pv/json.h"
|
|
||||||
|
|
||||||
namespace pvd = epics::pvData;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
struct args {
|
|
||||||
std::ostream& strm;
|
|
||||||
const pvd::JSONPrintOptions& opts;
|
|
||||||
|
|
||||||
unsigned indent;
|
|
||||||
|
|
||||||
args(std::ostream& strm,
|
|
||||||
const pvd::JSONPrintOptions& opts)
|
|
||||||
:strm(strm)
|
|
||||||
,opts(opts)
|
|
||||||
,indent(opts.indent)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void doIntent() {
|
|
||||||
if(!opts.multiLine) return;
|
|
||||||
strm.put('\n');
|
|
||||||
unsigned i=indent;
|
|
||||||
while(i--) strm.put(' ');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void show_field(args& A, const pvd::PVField* fld, const pvd::BitSet *mask);
|
|
||||||
|
|
||||||
void show_struct(args& A, const pvd::PVStructure* fld, const pvd::BitSet *mask)
|
|
||||||
{
|
|
||||||
const pvd::StructureConstPtr& type = fld->getStructure();
|
|
||||||
const pvd::PVFieldPtrArray& children = fld->getPVFields();
|
|
||||||
|
|
||||||
const pvd::StringArray& names = type->getFieldNames();
|
|
||||||
|
|
||||||
A.strm.put('{');
|
|
||||||
A.indent++;
|
|
||||||
|
|
||||||
bool first = true;
|
|
||||||
for(size_t i=0, N=names.size(); i<N; i++)
|
|
||||||
{
|
|
||||||
if(mask && !mask->get(children[i]->getFieldOffset())) continue;
|
|
||||||
|
|
||||||
if(first)
|
|
||||||
first = false;
|
|
||||||
else
|
|
||||||
A.strm.put(',');
|
|
||||||
A.doIntent();
|
|
||||||
A.strm<<'\"'<<names[i]<<"\": ";
|
|
||||||
show_field(A, children[i].get(), mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
A.indent--;
|
|
||||||
A.doIntent();
|
|
||||||
A.strm.put('}');
|
|
||||||
}
|
|
||||||
|
|
||||||
void show_field(args& A, const pvd::PVField* fld, const pvd::BitSet *mask)
|
|
||||||
{
|
|
||||||
switch(fld->getField()->getType())
|
|
||||||
{
|
|
||||||
case pvd::scalar:
|
|
||||||
{
|
|
||||||
const pvd::PVScalar *scalar=static_cast<const pvd::PVScalar*>(fld);
|
|
||||||
if(scalar->getScalar()->getScalarType()==pvd::pvString) {
|
|
||||||
A.strm<<'\"'<<scalar->getAs<std::string>()<<'\"';
|
|
||||||
} else {
|
|
||||||
A.strm<<scalar->getAs<std::string>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case pvd::scalarArray:
|
|
||||||
{
|
|
||||||
const pvd::PVScalarArray *scalar=static_cast<const pvd::PVScalarArray*>(fld);
|
|
||||||
const bool isstring = scalar->getScalarArray()->getElementType()==pvd::pvString;
|
|
||||||
|
|
||||||
pvd::shared_vector<const void> arr;
|
|
||||||
scalar->getAs<void>(arr);
|
|
||||||
|
|
||||||
pvd::shared_vector<const std::string> sarr(pvd::shared_vector_convert<const std::string>(arr));
|
|
||||||
|
|
||||||
A.strm.put('[');
|
|
||||||
for(size_t i=0, N=sarr.size(); i<N; i++) {
|
|
||||||
if(i!=0)
|
|
||||||
A.strm.put(',');
|
|
||||||
if(isstring)
|
|
||||||
A.strm.put('\"');
|
|
||||||
A.strm<<sarr[i];
|
|
||||||
if(isstring)
|
|
||||||
A.strm.put('\"');
|
|
||||||
}
|
|
||||||
A.strm.put(']');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case pvd::structure:
|
|
||||||
show_struct(A, static_cast<const pvd::PVStructure*>(fld), mask);
|
|
||||||
return;
|
|
||||||
case pvd::structureArray:
|
|
||||||
{
|
|
||||||
pvd::PVStructureArray::const_svector arr(static_cast<const pvd::PVStructureArray*>(fld)->view());
|
|
||||||
A.strm.put('[');
|
|
||||||
A.indent++;
|
|
||||||
|
|
||||||
for(size_t i=0, N=arr.size(); i<N; i++) {
|
|
||||||
if(i!=0)
|
|
||||||
A.strm.put(',');
|
|
||||||
A.doIntent();
|
|
||||||
if(arr[i])
|
|
||||||
show_struct(A, arr[i].get(), 0);
|
|
||||||
else
|
|
||||||
A.strm<<"NULL";
|
|
||||||
}
|
|
||||||
|
|
||||||
A.indent--;
|
|
||||||
A.doIntent();
|
|
||||||
A.strm.put(']');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case pvd::union_:
|
|
||||||
{
|
|
||||||
const pvd::PVUnion *U=static_cast<const pvd::PVUnion*>(fld);
|
|
||||||
const pvd::PVField::const_shared_pointer& C(U->get());
|
|
||||||
|
|
||||||
if(!C) {
|
|
||||||
A.strm<<"null";
|
|
||||||
} else {
|
|
||||||
show_field(A, C.get(), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case pvd::unionArray: {
|
|
||||||
const pvd::PVUnionArray *U=static_cast<const pvd::PVUnionArray*>(fld);
|
|
||||||
pvd::PVUnionArray::const_svector arr(U->view());
|
|
||||||
A.strm.put('[');
|
|
||||||
A.indent++;
|
|
||||||
|
|
||||||
for(size_t i=0, N=arr.size(); i<N; i++) {
|
|
||||||
if(i!=0)
|
|
||||||
A.strm.put(',');
|
|
||||||
A.doIntent();
|
|
||||||
if(arr[i])
|
|
||||||
show_field(A, arr[i].get(), 0);
|
|
||||||
else
|
|
||||||
A.strm<<"NULL";
|
|
||||||
}
|
|
||||||
|
|
||||||
A.indent--;
|
|
||||||
A.doIntent();
|
|
||||||
A.strm.put(']');
|
|
||||||
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// should not be reached
|
|
||||||
if(A.opts.ignoreUnprintable)
|
|
||||||
A.strm<<"// unprintable field type";
|
|
||||||
else
|
|
||||||
throw std::runtime_error("Encountered unprintable field type");
|
|
||||||
}
|
|
||||||
|
|
||||||
void expandBS(const pvd::PVStructure& top, pvd::BitSet& mask, bool parents) {
|
|
||||||
if(mask.get(0)) { // special handling because getSubField(0) not allowed
|
|
||||||
// wildcard
|
|
||||||
for(size_t idx=1, N=top.getNumberFields(); idx<N; idx++) {
|
|
||||||
mask.set(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
for(pvd::int32 idx = mask.nextSetBit(0), N=top.getNumberFields(); idx>=0 && idx<N; idx=mask.nextSetBit(idx+1)) {
|
|
||||||
pvd::PVField::const_shared_pointer fld = top.getSubFieldT(idx);
|
|
||||||
|
|
||||||
// look forward and mark all children
|
|
||||||
for(size_t i=idx+1, N=fld->getNextFieldOffset(); i<N; i++)
|
|
||||||
mask.set(i);
|
|
||||||
|
|
||||||
if(parents) {
|
|
||||||
// look back and mark all parents
|
|
||||||
// we've already stepped past all parents so siblings will not be automatically marked
|
|
||||||
for(const pvd::PVStructure *parent = fld->getParent(); parent; parent = parent->getParent()) {
|
|
||||||
mask.set(parent->getFieldOffset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace epics{namespace pvData{
|
|
||||||
|
|
||||||
JSONPrintOptions::JSONPrintOptions()
|
|
||||||
:multiLine(true)
|
|
||||||
,ignoreUnprintable(true)
|
|
||||||
,indent(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void printJSON(std::ostream& strm,
|
|
||||||
const PVStructure& val,
|
|
||||||
const BitSet& mask,
|
|
||||||
const JSONPrintOptions& opts)
|
|
||||||
{
|
|
||||||
args A(strm, opts);
|
|
||||||
pvd::BitSet emask(mask);
|
|
||||||
expandBS(val, emask, true);
|
|
||||||
if(!emask.get(0)) return;
|
|
||||||
show_struct(A, &val, &emask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void printJSON(std::ostream& strm,
|
|
||||||
const PVField& val,
|
|
||||||
const JSONPrintOptions& opts)
|
|
||||||
{
|
|
||||||
args A(strm, opts);
|
|
||||||
show_field(A, &val, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}} // namespace epics::pvData
|
|
||||||
|
|
||||||
#endif // EPICS_VERSION_INT
|
|
||||||
@@ -13,8 +13,6 @@
|
|||||||
#include <pv/pvdVersion.h>
|
#include <pv/pvdVersion.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
|
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
|
||||||
|
|
||||||
#ifdef epicsExportSharedSymbols
|
#ifdef epicsExportSharedSymbols
|
||||||
# define pvjson_epicsExportSharedSymbols
|
# define pvjson_epicsExportSharedSymbols
|
||||||
# undef epicsExportSharedSymbols
|
# undef epicsExportSharedSymbols
|
||||||
@@ -46,6 +44,7 @@ struct epicsShareClass JSONPrintOptions
|
|||||||
bool multiLine; //!< include new lines
|
bool multiLine; //!< include new lines
|
||||||
bool ignoreUnprintable;//!< ignore union/union array when encountered
|
bool ignoreUnprintable;//!< ignore union/union array when encountered
|
||||||
unsigned indent; //!< Initial indentation (# of spaces)
|
unsigned indent; //!< Initial indentation (# of spaces)
|
||||||
|
bool json5; //!< Output extended JSON (eg. NaN). @since 8.1.0
|
||||||
JSONPrintOptions();
|
JSONPrintOptions();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -147,8 +146,4 @@ typedef size_t size_arg;
|
|||||||
|
|
||||||
}} // namespace epics::pvData
|
}} // namespace epics::pvData
|
||||||
|
|
||||||
#else
|
|
||||||
# error JSON parser requires EPICS Base >= 3.15.0.1
|
|
||||||
#endif // EPICS_VERSION_INT
|
|
||||||
|
|
||||||
#endif // PV_JSON_H
|
#endif // PV_JSON_H
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ AnyScalar::AnyScalar(const AnyScalar& o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if __cplusplus>=201103L
|
#if __cplusplus>=201103L
|
||||||
AnyScalar::AnyScalar(AnyScalar&& o)
|
AnyScalar::AnyScalar(AnyScalar&& o) noexcept
|
||||||
:_stype(o._stype)
|
:_stype(o._stype)
|
||||||
{
|
{
|
||||||
typedef std::string string;
|
typedef std::string string;
|
||||||
@@ -136,7 +136,7 @@ void AnyScalar::swap(AnyScalar& o) {
|
|||||||
}
|
}
|
||||||
const void* AnyScalar::bufferUnsafe() const {
|
const void* AnyScalar::bufferUnsafe() const {
|
||||||
if(_stype==pvString) {
|
if(_stype==pvString) {
|
||||||
return as<std::string>().c_str();
|
return ref<std::string>().c_str();
|
||||||
} else {
|
} else {
|
||||||
return _wrap.blob;
|
return _wrap.blob;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ namespace epics { namespace pvData {
|
|||||||
|
|
||||||
void BitSet::deserialize(ByteBuffer* buffer, DeserializableControl* control) {
|
void BitSet::deserialize(ByteBuffer* buffer, DeserializableControl* control) {
|
||||||
|
|
||||||
uint32 bytes = static_cast<uint32>(SerializeHelper::readSize(buffer, control)); // in bytes
|
uint32 bytes = static_cast<uint32>(SerializeHelper::readSize(buffer, control)); // in bytes
|
||||||
|
|
||||||
size_t wordsInUse = (bytes + 7) / BYTES_PER_WORD;
|
size_t wordsInUse = (bytes + 7) / BYTES_PER_WORD;
|
||||||
words.resize(wordsInUse);
|
words.resize(wordsInUse);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ void shared_ptr_base::track_new()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create new tracker if ptr!=nullptr, otherwise clear
|
// create new tracker if ptr!=nullptr, otherwise clear
|
||||||
void shared_ptr_base::track_new(void* ptr)
|
void shared_ptr_base::track_new(const void* ptr)
|
||||||
{
|
{
|
||||||
track_clear();
|
track_clear();
|
||||||
if(ptr){
|
if(ptr){
|
||||||
|
|||||||
@@ -25,406 +25,6 @@ using std::string;
|
|||||||
#define NEED_LONGLONG
|
#define NEED_LONGLONG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EPICS_VERSION_INT
|
|
||||||
#define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
|
|
||||||
#define EPICS_VERSION_INT VERSION_INT(EPICS_VERSION, EPICS_REVISION, EPICS_MODIFICATION, EPICS_PATCH_LEVEL)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if EPICS_VERSION_INT < VERSION_INT(3,15,0,1)
|
|
||||||
/* These integer conversion primitives added to epicsStdlib.c in 3.15.0.1 */
|
|
||||||
|
|
||||||
#define S_stdlib_noConversion 1 /* No digits to convert */
|
|
||||||
#define S_stdlib_extraneous 2 /* Extraneous characters */
|
|
||||||
#define S_stdlib_underflow 3 /* Too small to represent */
|
|
||||||
#define S_stdlib_overflow 4 /* Too large to represent */
|
|
||||||
#define S_stdlib_badBase 5 /* Number base not supported */
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseLong(const char *str, long *to, int base, char **units)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
char *endp;
|
|
||||||
long value;
|
|
||||||
|
|
||||||
while ((c = *str) && isspace(c))
|
|
||||||
++str;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
value = strtol(str, &endp, base);
|
|
||||||
|
|
||||||
if (endp == str)
|
|
||||||
return S_stdlib_noConversion;
|
|
||||||
if (errno == EINVAL) /* Not universally supported */
|
|
||||||
return S_stdlib_badBase;
|
|
||||||
if (errno == ERANGE)
|
|
||||||
return S_stdlib_overflow;
|
|
||||||
|
|
||||||
while ((c = *endp) && isspace(c))
|
|
||||||
++endp;
|
|
||||||
if (c && !units)
|
|
||||||
return S_stdlib_extraneous;
|
|
||||||
|
|
||||||
*to = value;
|
|
||||||
if (units)
|
|
||||||
*units = endp;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseULong(const char *str, unsigned long *to, int base, char **units)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
char *endp;
|
|
||||||
unsigned long value;
|
|
||||||
|
|
||||||
while ((c = *str) && isspace(c))
|
|
||||||
++str;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
value = strtoul(str, &endp, base);
|
|
||||||
|
|
||||||
if (endp == str)
|
|
||||||
return S_stdlib_noConversion;
|
|
||||||
if (errno == EINVAL) /* Not universally supported */
|
|
||||||
return S_stdlib_badBase;
|
|
||||||
if (errno == ERANGE)
|
|
||||||
return S_stdlib_overflow;
|
|
||||||
|
|
||||||
while ((c = *endp) && isspace(c))
|
|
||||||
++endp;
|
|
||||||
if (c && !units)
|
|
||||||
return S_stdlib_extraneous;
|
|
||||||
|
|
||||||
*to = value;
|
|
||||||
if (units)
|
|
||||||
*units = endp;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseDouble(const char *str, double *to, char **units)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
char *endp;
|
|
||||||
double value;
|
|
||||||
|
|
||||||
while ((c = *str) && isspace(c))
|
|
||||||
++str;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
value = epicsStrtod(str, &endp);
|
|
||||||
|
|
||||||
if (endp == str)
|
|
||||||
return S_stdlib_noConversion;
|
|
||||||
if (errno == ERANGE)
|
|
||||||
return (value == 0) ? S_stdlib_underflow : S_stdlib_overflow;
|
|
||||||
|
|
||||||
while ((c = *endp) && isspace(c))
|
|
||||||
++endp;
|
|
||||||
if (c && !units)
|
|
||||||
return S_stdlib_extraneous;
|
|
||||||
|
|
||||||
*to = value;
|
|
||||||
if (units)
|
|
||||||
*units = endp;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* These call the primitives */
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseInt8(const char *str, epicsInt8 *to, int base, char **units)
|
|
||||||
{
|
|
||||||
long value;
|
|
||||||
int status = epicsParseLong(str, &value, base, units);
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (value < -0x80 || value > 0x7f)
|
|
||||||
return S_stdlib_overflow;
|
|
||||||
|
|
||||||
*to = (epicsInt8)value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseUInt8(const char *str, epicsUInt8 *to, int base, char **units)
|
|
||||||
{
|
|
||||||
unsigned long value;
|
|
||||||
int status = epicsParseULong(str, &value, base, units);
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (value > 0xff && value <= ~0xffUL)
|
|
||||||
return S_stdlib_overflow;
|
|
||||||
|
|
||||||
*to = (epicsUInt8)value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseInt16(const char *str, epicsInt16 *to, int base, char **units)
|
|
||||||
{
|
|
||||||
long value;
|
|
||||||
int status = epicsParseLong(str, &value, base, units);
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (value < -0x8000 || value > 0x7fff)
|
|
||||||
return S_stdlib_overflow;
|
|
||||||
|
|
||||||
*to = (epicsInt16)value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseUInt16(const char *str, epicsUInt16 *to, int base, char **units)
|
|
||||||
{
|
|
||||||
unsigned long value;
|
|
||||||
int status = epicsParseULong(str, &value, base, units);
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (value > 0xffff && value <= ~0xffffUL)
|
|
||||||
return S_stdlib_overflow;
|
|
||||||
|
|
||||||
*to = (epicsUInt16)value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseInt32(const char *str, epicsInt32 *to, int base, char **units)
|
|
||||||
{
|
|
||||||
long value;
|
|
||||||
int status = epicsParseLong(str, &value, base, units);
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
#if (LONG_MAX > 0x7fffffff)
|
|
||||||
if (value < -0x80000000L || value > 0x7fffffffL)
|
|
||||||
return S_stdlib_overflow;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*to = (epicsInt32)value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
|
|
||||||
{
|
|
||||||
unsigned long value;
|
|
||||||
int status = epicsParseULong(str, &value, base, units);
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
#if (ULONG_MAX > 0xffffffff)
|
|
||||||
if (value > 0xffffffffUL && value <= ~0xffffffffUL)
|
|
||||||
return S_stdlib_overflow;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*to = (epicsUInt32)value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
epicsParseFloat(const char *str, float *to, char **units)
|
|
||||||
{
|
|
||||||
double value, abs;
|
|
||||||
int status = epicsParseDouble(str, &value, units);
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
abs = fabs(value);
|
|
||||||
if (value > 0 && abs <= FLT_MIN)
|
|
||||||
return S_stdlib_underflow;
|
|
||||||
if (finite(value) && abs >= FLT_MAX)
|
|
||||||
return S_stdlib_overflow;
|
|
||||||
|
|
||||||
*to = (float)value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Sometimes we have to provide our own copy of strtoll()
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
|
||||||
// On Windows with MSVC, Base-3.15 provides strtoll()
|
|
||||||
# define NEED_OLL_FUNCS (EPICS_VERSION_INT < VERSION_INT(3,15,0,1))
|
|
||||||
#elif defined(vxWorks)
|
|
||||||
// On VxWorks, Base-3.15 provides strtoll()
|
|
||||||
# define NEED_OLL_FUNCS (EPICS_VERSION_INT < VERSION_INT(3,15,0,1))
|
|
||||||
#else
|
|
||||||
// Other architectures all provide strtoll()
|
|
||||||
# define NEED_OLL_FUNCS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(NEED_LONGLONG) && NEED_OLL_FUNCS
|
|
||||||
static
|
|
||||||
long long strtoll(const char *ptr, char ** endp, int base)
|
|
||||||
{
|
|
||||||
size_t inlen = strlen(ptr);
|
|
||||||
long long result;
|
|
||||||
unsigned char offset=0;
|
|
||||||
|
|
||||||
assert(base==0);
|
|
||||||
|
|
||||||
if(ptr[0]=='-')
|
|
||||||
offset=1;
|
|
||||||
|
|
||||||
try {
|
|
||||||
std::istringstream strm(ptr);
|
|
||||||
|
|
||||||
assert(strm.rdbuf()->in_avail()>=0
|
|
||||||
&& inlen==(size_t)strm.rdbuf()->in_avail());
|
|
||||||
|
|
||||||
if(ptr[offset]=='0') {
|
|
||||||
if(ptr[offset+1]=='x')
|
|
||||||
strm >> std::hex;
|
|
||||||
else
|
|
||||||
strm >> std::oct;
|
|
||||||
}
|
|
||||||
|
|
||||||
strm >> result;
|
|
||||||
if(strm.fail())
|
|
||||||
goto noconvert;
|
|
||||||
|
|
||||||
assert(strm.rdbuf()->in_avail()>=0
|
|
||||||
&& inlen>=(size_t)strm.rdbuf()->in_avail());
|
|
||||||
|
|
||||||
size_t consumed = inlen - strm.rdbuf()->in_avail();
|
|
||||||
*endp = (char*)ptr + consumed;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
} catch(...) {
|
|
||||||
goto noconvert;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
noconvert:
|
|
||||||
*endp = (char*)ptr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(vxWorks)
|
|
||||||
/* The VxWorks version of std::istringstream >> uint64_t is buggy,
|
|
||||||
* provide our own implementation
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
unsigned long long strtoull(const char *nptr, char **endptr, int base)
|
|
||||||
{
|
|
||||||
const char *s = nptr;
|
|
||||||
unsigned long long acc;
|
|
||||||
int c;
|
|
||||||
unsigned long long cutoff;
|
|
||||||
int neg = 0, any, cutlim;
|
|
||||||
|
|
||||||
do
|
|
||||||
c = *s++;
|
|
||||||
while (isspace(c));
|
|
||||||
if (c == '-')
|
|
||||||
{
|
|
||||||
neg = 1;
|
|
||||||
c = *s++;
|
|
||||||
}
|
|
||||||
else if (c == '+')
|
|
||||||
c = *s++;
|
|
||||||
if ((base == 0 || base == 16) &&
|
|
||||||
c == '0' && (*s == 'x' || *s == 'X'))
|
|
||||||
{
|
|
||||||
c = s[1];
|
|
||||||
s += 2;
|
|
||||||
base = 16;
|
|
||||||
}
|
|
||||||
if (base == 0)
|
|
||||||
base = c == '0' ? 8 : 10;
|
|
||||||
|
|
||||||
cutoff = (unsigned long long) UINT64_MAX / (unsigned long long) base;
|
|
||||||
cutlim = (unsigned long long) UINT64_MAX % (unsigned long long) base;
|
|
||||||
|
|
||||||
for (acc = 0, any = 0;; c = *s++)
|
|
||||||
{
|
|
||||||
if (isdigit(c))
|
|
||||||
c -= '0';
|
|
||||||
else if (isalpha(c))
|
|
||||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
if (c >= base)
|
|
||||||
break;
|
|
||||||
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
|
||||||
any = -1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
any = 1;
|
|
||||||
acc *= base;
|
|
||||||
acc += c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (any < 0)
|
|
||||||
{
|
|
||||||
acc = UINT64_MAX;
|
|
||||||
errno = ERANGE;
|
|
||||||
}
|
|
||||||
else if (neg)
|
|
||||||
acc = -acc;
|
|
||||||
if (endptr != 0)
|
|
||||||
*endptr = any ? (char *) s - 1 : (char *) nptr;
|
|
||||||
return (acc);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static
|
|
||||||
unsigned long long strtoull(const char *ptr, char ** endp, int base)
|
|
||||||
{
|
|
||||||
size_t inlen = strlen(ptr);
|
|
||||||
unsigned long long result;
|
|
||||||
|
|
||||||
assert(base==0);
|
|
||||||
|
|
||||||
try {
|
|
||||||
std::istringstream strm(ptr);
|
|
||||||
|
|
||||||
assert(strm.rdbuf()->in_avail()>=0
|
|
||||||
&& inlen==(size_t)strm.rdbuf()->in_avail());
|
|
||||||
|
|
||||||
if(ptr[0]=='0') {
|
|
||||||
if(ptr[1]=='x')
|
|
||||||
strm >> std::hex;
|
|
||||||
else
|
|
||||||
strm >> std::oct;
|
|
||||||
}
|
|
||||||
|
|
||||||
strm >> result;
|
|
||||||
if(strm.fail())
|
|
||||||
goto noconvert;
|
|
||||||
|
|
||||||
assert(strm.rdbuf()->in_avail()>=0
|
|
||||||
&& inlen>=(size_t)strm.rdbuf()->in_avail());
|
|
||||||
|
|
||||||
size_t consumed = inlen - strm.rdbuf()->in_avail();
|
|
||||||
*endp = (char*)ptr + consumed;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
} catch(...) {
|
|
||||||
goto noconvert;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
noconvert:
|
|
||||||
*endp = (char*)ptr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* do we need long long? */
|
/* do we need long long? */
|
||||||
#ifdef NEED_LONGLONG
|
#ifdef NEED_LONGLONG
|
||||||
static int
|
static int
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public:
|
|||||||
AnyScalar(const AnyScalar& o);
|
AnyScalar(const AnyScalar& o);
|
||||||
|
|
||||||
#if __cplusplus>=201103L
|
#if __cplusplus>=201103L
|
||||||
AnyScalar(AnyScalar&& o);
|
AnyScalar(AnyScalar&& o) noexcept;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline ~AnyScalar() {clear();}
|
inline ~AnyScalar() {clear();}
|
||||||
@@ -140,7 +140,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if __cplusplus>=201103L
|
#if __cplusplus>=201103L
|
||||||
inline AnyScalar& operator=(AnyScalar&& o) {
|
inline AnyScalar& operator=(AnyScalar&& o) noexcept {
|
||||||
clear();
|
clear();
|
||||||
swap(o);
|
swap(o);
|
||||||
return *this;
|
return *this;
|
||||||
|
|||||||
@@ -150,14 +150,17 @@ struct swap<8> {
|
|||||||
#undef _PVA_swap64
|
#undef _PVA_swap64
|
||||||
|
|
||||||
/* PVD serialization doesn't pay attention to alignement,
|
/* PVD serialization doesn't pay attention to alignement,
|
||||||
* which some targets really care about and treat unaligned
|
* which some targets (ARM and powerpc) really care about and treat unaligned
|
||||||
* access as a fault, or with a heavy penalty (~= to a syscall).
|
* access as a fault, or with a heavy penalty (~= to a syscall).
|
||||||
*
|
*
|
||||||
* For those targets,, we will have to live with the increase
|
* For those targets,, we will have to live with the increase
|
||||||
* in execution time and/or object code size of byte-wise copy.
|
* in execution time and/or object code size of byte-wise copy.
|
||||||
|
*
|
||||||
|
* Treat x86 32/64 as an outlier, and assume all other targets
|
||||||
|
* need, or greatly benefit, from aligned access.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _ARCH_PPC
|
#if !(defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86))
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
union alignu {
|
union alignu {
|
||||||
@@ -494,23 +497,6 @@ public:
|
|||||||
{
|
{
|
||||||
return sizeof(T)>1 && _reverseEndianess;
|
return sizeof(T)>1 && _reverseEndianess;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Adjust position to the next multiple of 'size.
|
|
||||||
* @param size The alignment requirement, must be a power of 2. (unchecked)
|
|
||||||
* @param fill value to use for padding bytes (default '\0').
|
|
||||||
*
|
|
||||||
* @note This alignment is absolute, not necessarily with respect to _buffer.
|
|
||||||
*/
|
|
||||||
inline void align(std::size_t size, char fill='\0')
|
|
||||||
{
|
|
||||||
const std::size_t k = size - 1, bufidx = (std::size_t)_position;
|
|
||||||
if(bufidx&k) {
|
|
||||||
std::size_t npad = size-(bufidx&k);
|
|
||||||
assert(npad<=getRemaining());
|
|
||||||
std::fill(_position, _position+npad, fill);
|
|
||||||
_position += npad;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Put a boolean value into the byte buffer.
|
* Put a boolean value into the byte buffer.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ protected:
|
|||||||
// add ourselves to tracker
|
// add ourselves to tracker
|
||||||
void track_new();
|
void track_new();
|
||||||
// create new tracker if ptr!=nullptr, otherwise clear
|
// create new tracker if ptr!=nullptr, otherwise clear
|
||||||
void track_new(void* ptr);
|
void track_new(const void* ptr);
|
||||||
// copy tracker and add ourself
|
// copy tracker and add ourself
|
||||||
void track_assign(const shared_ptr_base& o);
|
void track_assign(const shared_ptr_base& o);
|
||||||
void track_clear();
|
void track_clear();
|
||||||
@@ -286,6 +286,7 @@ public:
|
|||||||
|
|
||||||
long use_count() const noexcept { return real.use_count(); }
|
long use_count() const noexcept { return real.use_count(); }
|
||||||
bool unique() const noexcept { return real.unique(); }
|
bool unique() const noexcept { return real.unique(); }
|
||||||
|
bool expired() const noexcept { return real.expired(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Base>
|
template<class Base>
|
||||||
@@ -316,13 +317,12 @@ do_enable_shared_from_this(const shared_ptr<Store>& dest,
|
|||||||
self->xxInternalSelf = actual;
|
self->xxInternalSelf = actual;
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namespace epics::debug
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::ostream& operator<<(std::ostream& strm, const epics::debug::shared_ptr<T>& ptr)
|
inline std::ostream& operator<<(std::ostream& strm, const shared_ptr<T>& ptr)
|
||||||
{
|
{
|
||||||
strm<<ptr.get();
|
strm<<ptr.get();
|
||||||
return strm;
|
return strm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}} // namespace epics::debug
|
||||||
#endif // DEBUGPTR_H
|
#endif // DEBUGPTR_H
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
explicit BaseException(const std::string msg) : std::logic_error(msg) {}
|
explicit BaseException(const std::string& msg) : std::logic_error(msg) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor.
|
* Destructor.
|
||||||
@@ -229,7 +229,6 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define THROW_BASE_EXCEPTION(msg) THROW_EXCEPTION2(::epics::pvData::BaseException, msg)
|
#define THROW_BASE_EXCEPTION(msg) THROW_EXCEPTION2(::epics::pvData::BaseException, msg)
|
||||||
#define THROW_BASE_EXCEPTION_CAUSE(msg, cause) THROW_EXCEPTION2(::epics::pvData::BaseException, msg)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,27 +46,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <epicsVersion.h>
|
#include <epicsVersion.h>
|
||||||
|
#include <epicsAtomic.h>
|
||||||
|
|
||||||
#ifndef VERSION_INT
|
#define REFTRACE_INCREMENT(counter) ::epics::atomic::increment(counter)
|
||||||
# define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
|
#define REFTRACE_DECREMENT(counter) ::epics::atomic::decrement(counter)
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EPICS_VERSION_INT
|
|
||||||
# define EPICS_VERSION_INT VERSION_INT(EPICS_VERSION, EPICS_REVISION, EPICS_MODIFICATION, EPICS_PATCH_LEVEL)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,1,0)
|
|
||||||
# include <epicsAtomic.h>
|
|
||||||
# define REFTRACK_USE_ATOMIC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef REFTRACK_USE_ATOMIC
|
|
||||||
# define REFTRACE_INCREMENT(counter) ::epics::atomic::increment(counter)
|
|
||||||
# define REFTRACE_DECREMENT(counter) ::epics::atomic::decrement(counter)
|
|
||||||
#else
|
|
||||||
# define REFTRACE_INCREMENT(counter) do{}while(0)
|
|
||||||
# define REFTRACE_DECREMENT(counter) do{}while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,14 @@
|
|||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
#if defined(PVD_INTERNAL)
|
||||||
|
# define PVD_DEPRECATED(msg)
|
||||||
|
#elif __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 5
|
||||||
|
# define PVD_DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||||
|
#else
|
||||||
|
# define PVD_DEPRECATED(msg) EPICS_DEPRECATED
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace epics { namespace pvData {
|
namespace epics { namespace pvData {
|
||||||
|
|
||||||
class SerializableControl;
|
class SerializableControl;
|
||||||
@@ -47,11 +55,7 @@ namespace epics { namespace pvData {
|
|||||||
* @param size The number of bytes.
|
* @param size The number of bytes.
|
||||||
*/
|
*/
|
||||||
virtual void ensureBuffer(std::size_t size) =0;
|
virtual void ensureBuffer(std::size_t size) =0;
|
||||||
/**
|
virtual void alignBuffer(std::size_t alignment) PVD_DEPRECATED("Deprecated for lack of use") {}
|
||||||
* Add pad bytes to buffer.
|
|
||||||
* @param alignment alignment required.
|
|
||||||
*/
|
|
||||||
virtual void alignBuffer(std::size_t alignment) =0;
|
|
||||||
/**
|
/**
|
||||||
* Method for serializing primitive array data.
|
* Method for serializing primitive array data.
|
||||||
* Hook for supplying custom serialization implementation.
|
* Hook for supplying custom serialization implementation.
|
||||||
@@ -98,14 +102,8 @@ namespace epics { namespace pvData {
|
|||||||
* @param size The number of bytes.
|
* @param size The number of bytes.
|
||||||
*/
|
*/
|
||||||
virtual void ensureData(std::size_t size) =0;
|
virtual void ensureData(std::size_t size) =0;
|
||||||
/**
|
// Deprecated for lack of use
|
||||||
* Align buffer.
|
virtual void alignData(std::size_t alignment) PVD_DEPRECATED("Deprecated for lack of use") {};
|
||||||
* Note that this takes care only current buffer alignment.
|
|
||||||
* If streaming protocol is used,
|
|
||||||
* care must be taken that entire stream is aligned.
|
|
||||||
* @param alignment size in bytes, must be power of two.
|
|
||||||
*/
|
|
||||||
virtual void alignData(std::size_t alignment) =0;
|
|
||||||
/**
|
/**
|
||||||
* Method for deserializing array data.
|
* Method for deserializing array data.
|
||||||
* Hook for supplying custom deserialization implementation.
|
* Hook for supplying custom deserialization implementation.
|
||||||
@@ -150,7 +148,7 @@ namespace epics { namespace pvData {
|
|||||||
*/
|
*/
|
||||||
virtual void serialize(ByteBuffer *buffer,
|
virtual void serialize(ByteBuffer *buffer,
|
||||||
SerializableControl *flusher) const = 0;
|
SerializableControl *flusher) const = 0;
|
||||||
/**
|
/**
|
||||||
* Deserialize buffer.
|
* Deserialize buffer.
|
||||||
* @param buffer serialization buffer.
|
* @param buffer serialization buffer.
|
||||||
* @param flusher deserialization control.
|
* @param flusher deserialization control.
|
||||||
@@ -213,7 +211,7 @@ namespace epics { namespace pvData {
|
|||||||
*/
|
*/
|
||||||
virtual void serialize(ByteBuffer *buffer,
|
virtual void serialize(ByteBuffer *buffer,
|
||||||
SerializableControl *flusher,BitSet *bitSet) const = 0;
|
SerializableControl *flusher,BitSet *bitSet) const = 0;
|
||||||
/**
|
/**
|
||||||
* Deserialize buffer.
|
* Deserialize buffer.
|
||||||
* @param buffer serialization buffer.
|
* @param buffer serialization buffer.
|
||||||
* @param flusher deserialization control.
|
* @param flusher deserialization control.
|
||||||
|
|||||||
@@ -434,11 +434,11 @@ public:
|
|||||||
_E_non_const* temp=new _E_non_const[i];
|
_E_non_const* temp=new _E_non_const[i];
|
||||||
try{
|
try{
|
||||||
std::copy(begin(), begin()+new_count, temp);
|
std::copy(begin(), begin()+new_count, temp);
|
||||||
this->m_sdata.reset(temp, detail::default_array_deleter<E*>());
|
|
||||||
}catch(...){
|
}catch(...){
|
||||||
delete[] temp;
|
delete[] temp;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
this->m_sdata.reset(temp, detail::default_array_deleter<E*>());
|
||||||
this->m_offset = 0;
|
this->m_offset = 0;
|
||||||
this->m_count = new_count;
|
this->m_count = new_count;
|
||||||
this->m_total = i;
|
this->m_total = i;
|
||||||
@@ -481,11 +481,11 @@ public:
|
|||||||
std::copy(begin(),
|
std::copy(begin(),
|
||||||
begin()+n,
|
begin()+n,
|
||||||
temp);
|
temp);
|
||||||
this->m_sdata.reset(temp, detail::default_array_deleter<pointer>());
|
|
||||||
}catch(...){
|
}catch(...){
|
||||||
delete[] temp;
|
delete[] temp;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
this->m_sdata.reset(temp, detail::default_array_deleter<pointer>());
|
||||||
this->m_offset= 0;
|
this->m_offset= 0;
|
||||||
this->m_count = i;
|
this->m_count = i;
|
||||||
this->m_total = new_total;
|
this->m_total = new_total;
|
||||||
@@ -544,11 +544,11 @@ private:
|
|||||||
/* Hack alert.
|
/* Hack alert.
|
||||||
* For reasons of simplicity and efficiency, we want to use raw pointers for iteration.
|
* 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.
|
* 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.
|
* So we fudge here by abusing 'this' so that our iterators are always !NULL.
|
||||||
*/
|
*/
|
||||||
inline E* base_ptr() const {
|
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);
|
return this->m_count ? this->m_sdata.get() : (E*)(this-1);
|
||||||
#else
|
#else
|
||||||
return this->m_sdata.get();
|
return this->m_sdata.get();
|
||||||
@@ -837,9 +837,13 @@ namespace detail {
|
|||||||
typedef typename meta::strip_const<TO>::type to_t;
|
typedef typename meta::strip_const<TO>::type to_t;
|
||||||
ScalarType stype = src.original_type(),
|
ScalarType stype = src.original_type(),
|
||||||
dtype = (ScalarType)ScalarTypeID<TO>::value;
|
dtype = (ScalarType)ScalarTypeID<TO>::value;
|
||||||
if(stype==dtype) {
|
if(src.empty()) {
|
||||||
|
return shared_vector<TO>();
|
||||||
|
|
||||||
|
} else if(stype==dtype) {
|
||||||
// no convert needed
|
// no convert needed
|
||||||
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
|
return shared_vector<TO>(src, detail::_shared_vector_cast_tag());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// alloc and convert
|
// alloc and convert
|
||||||
shared_vector<to_t> ret(src.size()/ScalarTypeFunc::elementSize(stype));
|
shared_vector<to_t> ret(src.size()/ScalarTypeFunc::elementSize(stype));
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ namespace epics { namespace pvData {
|
|||||||
class epicsShareClass Status : public epics::pvData::Serializable {
|
class epicsShareClass Status : public epics::pvData::Serializable {
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(Status);
|
POINTER_DEFINITIONS(Status);
|
||||||
/**
|
/**
|
||||||
* Status type enum.
|
* Status type enum.
|
||||||
*/
|
*/
|
||||||
enum StatusType {
|
enum StatusType {
|
||||||
/** Operation completed successfully. */
|
/** Operation completed successfully. */
|
||||||
STATUSTYPE_OK,
|
STATUSTYPE_OK,
|
||||||
/** Operation completed successfully, but there is a warning message. */
|
/** Operation completed successfully, but there is a warning message. */
|
||||||
@@ -40,11 +40,11 @@ namespace epics { namespace pvData {
|
|||||||
STATUSTYPE_ERROR,
|
STATUSTYPE_ERROR,
|
||||||
/** Operation failed due to an unexpected error. */
|
/** Operation failed due to an unexpected error. */
|
||||||
STATUSTYPE_FATAL
|
STATUSTYPE_FATAL
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* StatusTypeName[];
|
static const char* StatusTypeName[];
|
||||||
|
|
||||||
static Status Ok;
|
static Status Ok;
|
||||||
|
|
||||||
static inline Status warn(const std::string& m) { return Status(STATUSTYPE_WARNING, m); }
|
static inline Status warn(const std::string& m) { return Status(STATUSTYPE_WARNING, m); }
|
||||||
static inline Status error(const std::string& m) { return Status(STATUSTYPE_ERROR, m); }
|
static inline Status error(const std::string& m) { return Status(STATUSTYPE_ERROR, m); }
|
||||||
@@ -55,9 +55,9 @@ namespace epics { namespace pvData {
|
|||||||
*/
|
*/
|
||||||
Status() :m_statusType(STATUSTYPE_OK) {}
|
Status() :m_statusType(STATUSTYPE_OK) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create non-OK status.
|
* Create non-OK status.
|
||||||
*/
|
*/
|
||||||
Status(StatusType type, std::string const & message);
|
Status(StatusType type, std::string const & message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ private:
|
|||||||
epicsTime timeToRun;
|
epicsTime timeToRun;
|
||||||
double period;
|
double period;
|
||||||
bool onList;
|
bool onList;
|
||||||
|
bool cancelled;
|
||||||
|
bool processing;
|
||||||
friend class Timer;
|
friend class Timer;
|
||||||
struct IncreasingTime;
|
struct IncreasingTime;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -237,6 +237,14 @@ public:
|
|||||||
std::ostream& operator<<(std::ostream& strm, const escape& Q);
|
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
|
}} // end namespace
|
||||||
|
|
||||||
#endif // PVTYPECAST_H
|
#endif // PVTYPECAST_H
|
||||||
|
|||||||
@@ -25,15 +25,6 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#ifndef REFTRACK_USE_ATOMIC
|
|
||||||
static inline
|
|
||||||
size_t readref(const size_t *ref)
|
|
||||||
{
|
|
||||||
volatile const size_t *vref = ref;
|
|
||||||
return *vref;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef epicsGuard<epicsMutex> Guard;
|
typedef epicsGuard<epicsMutex> Guard;
|
||||||
typedef epicsGuardRelease<epicsMutex> UnGuard;
|
typedef epicsGuardRelease<epicsMutex> UnGuard;
|
||||||
|
|
||||||
@@ -88,11 +79,7 @@ size_t readRefCounter(const char *name)
|
|||||||
refgbl_t::counters_t::iterator it(refgbl->counters.find(name));
|
refgbl_t::counters_t::iterator it(refgbl->counters.find(name));
|
||||||
if(it==refgbl->counters.end())
|
if(it==refgbl->counters.end())
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef REFTRACK_USE_ATOMIC
|
|
||||||
return atomic::get(*it->second);
|
return atomic::get(*it->second);
|
||||||
#else
|
|
||||||
return readref(it->second);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const RefSnapshot::Count&
|
const RefSnapshot::Count&
|
||||||
@@ -119,11 +106,7 @@ void RefSnapshot::update()
|
|||||||
end=counters.end();
|
end=counters.end();
|
||||||
it!=end; ++it)
|
it!=end; ++it)
|
||||||
{
|
{
|
||||||
#ifdef REFTRACK_USE_ATOMIC
|
|
||||||
size_t cnt = atomic::get(*it->second);
|
size_t cnt = atomic::get(*it->second);
|
||||||
#else
|
|
||||||
size_t cnt = readref(it->second);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
counts[it->first] = Count(cnt, 0);
|
counts[it->first] = Count(cnt, 0);
|
||||||
}
|
}
|
||||||
@@ -288,10 +271,10 @@ char* epicsRefSnapshotCurrent()
|
|||||||
snap.update();
|
snap.update();
|
||||||
std::ostringstream strm;
|
std::ostringstream strm;
|
||||||
strm<<snap;
|
strm<<snap;
|
||||||
const char *str = strm.str().c_str();
|
std::string str = strm.str();
|
||||||
char *ret = (char*)malloc(strlen(str)+1);
|
char *ret = (char*)malloc(str.length()+1);
|
||||||
if(ret)
|
if(ret)
|
||||||
strcpy(ret, str);
|
strcpy(ret, str.c_str());
|
||||||
return ret;
|
return ret;
|
||||||
}catch(std::exception& e){
|
}catch(std::exception& e){
|
||||||
return epicsStrDup(e.what());
|
return epicsStrDup(e.what());
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace epics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SerializeHelper::writeSize(std::size_t s, ByteBuffer* buffer) {
|
void SerializeHelper::writeSize(std::size_t s, ByteBuffer* buffer) {
|
||||||
if(s==(std::size_t)-1) // null // TODO remove
|
if(s==(std::size_t)-1) // null not a size, but used in PVUnion::serialize()
|
||||||
buffer->putByte(-1);
|
buffer->putByte(-1);
|
||||||
else if(s<254)
|
else if(s<254)
|
||||||
buffer->putByte(static_cast<int8>(s));
|
buffer->putByte(static_cast<int8>(s));
|
||||||
@@ -103,7 +103,7 @@ namespace epics {
|
|||||||
DeserializableControl* control) {
|
DeserializableControl* control) {
|
||||||
|
|
||||||
std::size_t size = SerializeHelper::readSize(buffer, control);
|
std::size_t size = SerializeHelper::readSize(buffer, control);
|
||||||
if(size!=(size_t)-1) // TODO null strings check, to be removed in the future
|
if(size!=(size_t)-1) // TODO null strings check, to be removed in the future
|
||||||
{
|
{
|
||||||
if (buffer->getRemaining()>=size)
|
if (buffer->getRemaining()>=size)
|
||||||
{
|
{
|
||||||
@@ -174,14 +174,6 @@ struct ToString : public epics::pvData::SerializableControl
|
|||||||
assert(bufwrap.getRemaining()>0);
|
assert(bufwrap.getRemaining()>0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void alignBuffer(std::size_t alignment)
|
|
||||||
{
|
|
||||||
if(bufwrap.getRemaining()<alignment)
|
|
||||||
flushSerializeBuffer();
|
|
||||||
assert(bufwrap.getRemaining()>=alignment);
|
|
||||||
bufwrap.align(alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool directSerialize(
|
virtual bool directSerialize(
|
||||||
ByteBuffer *existingBuffer,
|
ByteBuffer *existingBuffer,
|
||||||
const char* toSerialize,
|
const char* toSerialize,
|
||||||
@@ -232,16 +224,6 @@ struct FromString : public epics::pvData::DeserializableControl
|
|||||||
throw std::logic_error("Incomplete buffer");
|
throw std::logic_error("Incomplete buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void alignData(std::size_t alignment)
|
|
||||||
{
|
|
||||||
size_t pos = buf.getPosition(), k = alignment-1;
|
|
||||||
if(pos&k) {
|
|
||||||
std::size_t npad = alignment-(pos&k);
|
|
||||||
ensureData(npad);
|
|
||||||
buf.align(alignment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool directDeserialize(
|
virtual bool directDeserialize(
|
||||||
ByteBuffer *existingBuffer,
|
ByteBuffer *existingBuffer,
|
||||||
char* deserializeTo,
|
char* deserializeTo,
|
||||||
|
|||||||
@@ -44,40 +44,40 @@ void Status::maximize(const Status& o)
|
|||||||
|
|
||||||
void Status::serialize(ByteBuffer *buffer, SerializableControl *flusher) const
|
void Status::serialize(ByteBuffer *buffer, SerializableControl *flusher) const
|
||||||
{
|
{
|
||||||
flusher->ensureBuffer(1);
|
flusher->ensureBuffer(1);
|
||||||
if (m_statusType == STATUSTYPE_OK)
|
if (m_statusType == STATUSTYPE_OK)
|
||||||
{
|
{
|
||||||
// special code for okStatus (optimization)
|
// special code for okStatus (optimization)
|
||||||
buffer->putByte((int8)-1);
|
buffer->putByte((int8)-1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer->putByte((int8)m_statusType);
|
buffer->putByte((int8)m_statusType);
|
||||||
SerializeHelper::serializeString(m_message, buffer, flusher);
|
SerializeHelper::serializeString(m_message, buffer, flusher);
|
||||||
SerializeHelper::serializeString(m_stackDump, buffer, flusher);
|
SerializeHelper::serializeString(m_stackDump, buffer, flusher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Status::deserialize(ByteBuffer *buffer, DeserializableControl *flusher)
|
void Status::deserialize(ByteBuffer *buffer, DeserializableControl *flusher)
|
||||||
{
|
{
|
||||||
flusher->ensureData(1);
|
flusher->ensureData(1);
|
||||||
int8 typeCode = buffer->getByte();
|
int8 typeCode = buffer->getByte();
|
||||||
if (typeCode == (int8)-1)
|
if (typeCode == (int8)-1)
|
||||||
{
|
{
|
||||||
// in most of the cases status will be OK, we statistically optimize
|
// in most of the cases status will be OK, we statistically optimize
|
||||||
if (m_statusType != STATUSTYPE_OK)
|
if (m_statusType != STATUSTYPE_OK)
|
||||||
{
|
{
|
||||||
m_statusType = STATUSTYPE_OK;
|
m_statusType = STATUSTYPE_OK;
|
||||||
m_message.clear();
|
m_message.clear();
|
||||||
m_stackDump.clear();
|
m_stackDump.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_statusType = (StatusType)typeCode;
|
m_statusType = (StatusType)typeCode;
|
||||||
m_message = SerializeHelper::deserializeString(buffer, flusher);
|
m_message = SerializeHelper::deserializeString(buffer, flusher);
|
||||||
m_stackDump = SerializeHelper::deserializeString(buffer, flusher);
|
m_stackDump = SerializeHelper::deserializeString(buffer, flusher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Status::dump(std::ostream& o) const
|
void Status::dump(std::ostream& o) const
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ namespace epics { namespace pvData {
|
|||||||
|
|
||||||
TimerCallback::TimerCallback()
|
TimerCallback::TimerCallback()
|
||||||
: period(0.0),
|
: period(0.0),
|
||||||
onList(false)
|
onList(false),
|
||||||
|
cancelled(false),
|
||||||
|
processing(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +52,7 @@ void Timer::addElement(TimerCallbackPtr const & timerCallback)
|
|||||||
temp.push_back(timerCallback);
|
temp.push_back(timerCallback);
|
||||||
|
|
||||||
timerCallback->onList = true;
|
timerCallback->onList = true;
|
||||||
|
timerCallback->cancelled = false;
|
||||||
|
|
||||||
// merge sorted lists.
|
// merge sorted lists.
|
||||||
// for us effectively insertion sort.
|
// for us effectively insertion sort.
|
||||||
@@ -60,7 +63,16 @@ void Timer::addElement(TimerCallbackPtr const & timerCallback)
|
|||||||
bool Timer::cancel(TimerCallbackPtr const &timerCallback)
|
bool Timer::cancel(TimerCallbackPtr const &timerCallback)
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
|
/* If we're processing, just set the cancel flag */
|
||||||
|
if (timerCallback->processing) {
|
||||||
|
timerCallback->cancelled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if(!timerCallback->onList) return false;
|
if(!timerCallback->onList) return false;
|
||||||
|
if(!alive) {
|
||||||
|
timerCallback->onList = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
for(queue_t::iterator it(queue.begin()), end(queue.end()); it != end; ++it)
|
for(queue_t::iterator it(queue.begin()), end(queue.end()); it != end; ++it)
|
||||||
{
|
{
|
||||||
TimerCallbackPtr& cur = *it;
|
TimerCallbackPtr& cur = *it;
|
||||||
@@ -103,6 +115,7 @@ void Timer::run()
|
|||||||
TimerCallbackPtr work;
|
TimerCallbackPtr work;
|
||||||
work.swap(queue.front());
|
work.swap(queue.front());
|
||||||
work->onList = false;
|
work->onList = false;
|
||||||
|
work->processing = true;
|
||||||
queue.pop_front();
|
queue.pop_front();
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -111,7 +124,15 @@ void Timer::run()
|
|||||||
work->callback();
|
work->callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(work->period > 0.0) {
|
work->processing = false;
|
||||||
|
|
||||||
|
if(work->period > 0.0 && alive && !work->cancelled) {
|
||||||
|
if(waitfor <= -work->period) {
|
||||||
|
// Periodic timer phase has fallen behind by at least one full period.
|
||||||
|
// Could be due to previous slow jobs, or a system time jump forward.
|
||||||
|
// Reset the phase.
|
||||||
|
work->timeToRun = now = epicsTime::getCurrent();
|
||||||
|
}
|
||||||
work->timeToRun += work->period;
|
work->timeToRun += work->period;
|
||||||
addElement(work);
|
addElement(work);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,11 +44,6 @@ public:
|
|||||||
//default constructors and destructor are OK
|
//default constructors and destructor are OK
|
||||||
//returns (false,true) if pvField(is not, is) a valid alarm structure
|
//returns (false,true) if pvField(is not, is) a valid alarm structure
|
||||||
//An automatic detach is issued if already attached.
|
//An automatic detach is issued if already attached.
|
||||||
/*
|
|
||||||
* Attach to a field of a PVData object.
|
|
||||||
* @param pvField The pvField.
|
|
||||||
* @return (false,true) if the pvField (is not, is) an alarm structure.
|
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
* Attach to a field of a PVData object.
|
* Attach to a field of a PVData object.
|
||||||
* @param pvField The pvField.
|
* @param pvField The pvField.
|
||||||
|
|||||||
@@ -948,11 +948,11 @@ public:
|
|||||||
typedef PVUnion & reference;
|
typedef PVUnion & reference;
|
||||||
typedef const PVUnion & const_reference;
|
typedef const PVUnion & const_reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undefined index.
|
* Undefined index.
|
||||||
* Default value upon PVUnion construction. Can be set by the user.
|
* Default value upon PVUnion construction. Can be set by the user.
|
||||||
* Corresponds to @c null value.
|
* Corresponds to @c null value.
|
||||||
*/
|
*/
|
||||||
static const int32 UNDEFINED_INDEX;
|
static const int32 UNDEFINED_INDEX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1081,9 +1081,9 @@ private:
|
|||||||
friend class PVDataCreate;
|
friend class PVDataCreate;
|
||||||
UnionConstPtr unionPtr; // same as PVField::getField()
|
UnionConstPtr unionPtr; // same as PVField::getField()
|
||||||
|
|
||||||
int32 selector;
|
int32 selector;
|
||||||
PVFieldPtr value;
|
PVFieldPtr value;
|
||||||
bool variant;
|
bool variant;
|
||||||
EPICS_NOT_COPYABLE(PVUnion)
|
EPICS_NOT_COPYABLE(PVUnion)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -24,14 +24,6 @@
|
|||||||
#include <pv/pvdVersion.h>
|
#include <pv/pvdVersion.h>
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
|
||||||
#if defined(PVD_INTERNAL)
|
|
||||||
# define PVD_DEPRECATED(msg)
|
|
||||||
#elif __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 5
|
|
||||||
# define PVD_DEPRECATED(msg) __attribute__((deprecated(msg)))
|
|
||||||
#else
|
|
||||||
# define PVD_DEPRECATED(msg) EPICS_DEPRECATED
|
|
||||||
#endif
|
|
||||||
#define PVD_DEPRECATED_52 PVD_DEPRECATED("See https://github.com/epics-base/pvDataCPP/issues/52")
|
#define PVD_DEPRECATED_52 PVD_DEPRECATED("See https://github.com/epics-base/pvDataCPP/issues/52")
|
||||||
|
|
||||||
/* C++11 keywords
|
/* C++11 keywords
|
||||||
@@ -371,6 +363,7 @@ protected:
|
|||||||
* @param type The field type.
|
* @param type The field type.
|
||||||
*/
|
*/
|
||||||
Field(Type type);
|
Field(Type type);
|
||||||
|
void cacheCleanup();
|
||||||
private:
|
private:
|
||||||
const Type m_fieldType;
|
const Type m_fieldType;
|
||||||
unsigned int m_hash;
|
unsigned int m_hash;
|
||||||
@@ -1078,12 +1071,12 @@ public:
|
|||||||
//! Create a new instance of in-line @c Field builder pre-initialized with and existing Structure
|
//! Create a new instance of in-line @c Field builder pre-initialized with and existing Structure
|
||||||
static FieldBuilderPtr begin(StructureConstPtr S);
|
static FieldBuilderPtr begin(StructureConstPtr S);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set ID of an object to be created.
|
* Set ID of an object to be created.
|
||||||
* @param id id to be set.
|
* @param id id to be set.
|
||||||
* @return this instance of a @c FieldBuilder.
|
* @return this instance of a @c FieldBuilder.
|
||||||
*/
|
*/
|
||||||
FieldBuilderPtr setId(std::string const & id);
|
FieldBuilderPtr setId(std::string const & id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a @c Scalar.
|
* Add a @c Scalar.
|
||||||
@@ -1213,20 +1206,20 @@ private:
|
|||||||
FieldBuilder(const FieldBuilderPtr & _parentBuilder, const std::string& name, const Union*);
|
FieldBuilder(const FieldBuilderPtr & _parentBuilder, const std::string& name, const Union*);
|
||||||
FieldBuilder(const FieldBuilderPtr & _parentBuilder, const std::string& name, const UnionArray*);
|
FieldBuilder(const FieldBuilderPtr & _parentBuilder, const std::string& name, const UnionArray*);
|
||||||
FieldBuilder(FieldBuilderPtr const & parentBuilder,
|
FieldBuilder(FieldBuilderPtr const & parentBuilder,
|
||||||
std::string const & nestedName,
|
std::string const & nestedName,
|
||||||
Type nestedClassToBuild, bool nestedArray);
|
Type nestedClassToBuild, bool nestedArray);
|
||||||
|
|
||||||
const Field *findField(const std::string& name, Type ftype);
|
const Field *findField(const std::string& name, Type ftype);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
FieldConstPtr createFieldInternal(Type type);
|
FieldConstPtr createFieldInternal(Type type);
|
||||||
|
|
||||||
friend class FieldCreate;
|
friend class FieldCreate;
|
||||||
|
|
||||||
const FieldCreatePtr fieldCreate;
|
const FieldCreatePtr fieldCreate;
|
||||||
|
|
||||||
std::string id;
|
std::string id;
|
||||||
bool idSet;
|
bool idSet;
|
||||||
|
|
||||||
StringArray fieldNames;
|
StringArray fieldNames;
|
||||||
FieldConstPtrArray fields;
|
FieldConstPtrArray fields;
|
||||||
@@ -1250,11 +1243,11 @@ class epicsShareClass FieldCreate {
|
|||||||
friend struct detail::field_factory;
|
friend struct detail::field_factory;
|
||||||
public:
|
public:
|
||||||
static const FieldCreatePtr &getFieldCreate();
|
static const FieldCreatePtr &getFieldCreate();
|
||||||
/**
|
/**
|
||||||
* Create a new instance of in-line @c Field builder.
|
* Create a new instance of in-line @c Field builder.
|
||||||
* @return a new instance of a @c FieldBuilder.
|
* @return a new instance of a @c FieldBuilder.
|
||||||
*/
|
*/
|
||||||
FieldBuilderPtr createFieldBuilder() const;
|
FieldBuilderPtr createFieldBuilder() const;
|
||||||
/**
|
/**
|
||||||
* Create a new instance of in-line @c Field builder pre-initialized with and existing Structure
|
* Create a new instance of in-line @c Field builder pre-initialized with and existing Structure
|
||||||
* @return a new instance of a @c FieldBuilder.
|
* @return a new instance of a @c FieldBuilder.
|
||||||
@@ -1322,7 +1315,7 @@ public:
|
|||||||
* @return a @c Structure interface for the newly created object.
|
* @return a @c Structure interface for the newly created object.
|
||||||
*/
|
*/
|
||||||
StructureConstPtr createStructure (
|
StructureConstPtr createStructure (
|
||||||
std::string const & id,
|
std::string const & id,
|
||||||
StringArray const & fieldNames,
|
StringArray const & fieldNames,
|
||||||
FieldConstPtrArray const & fields) const;
|
FieldConstPtrArray const & fields) const;
|
||||||
/**
|
/**
|
||||||
@@ -1358,7 +1351,7 @@ public:
|
|||||||
* @return a @c Union interface for the newly created object.
|
* @return a @c Union interface for the newly created object.
|
||||||
*/
|
*/
|
||||||
UnionConstPtr createUnion (
|
UnionConstPtr createUnion (
|
||||||
std::string const & id,
|
std::string const & id,
|
||||||
StringArray const & fieldNames,
|
StringArray const & fieldNames,
|
||||||
FieldConstPtrArray const & fields) const;
|
FieldConstPtrArray const & fields) const;
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ include $(PVDATA_TEST)/pv/Makefile
|
|||||||
include $(PVDATA_TEST)/property/Makefile
|
include $(PVDATA_TEST)/property/Makefile
|
||||||
include $(PVDATA_TEST)/copy/Makefile
|
include $(PVDATA_TEST)/copy/Makefile
|
||||||
|
|
||||||
|
PROD_SRCS_RTEMS += rtemsTestData.c
|
||||||
|
|
||||||
# pvDataAllTests runs all the test programs in a known working order.
|
# pvDataAllTests runs all the test programs in a known working order.
|
||||||
testHarness_SRCS += pvDataAllTests.c
|
testHarness_SRCS += pvDataAllTests.c
|
||||||
|
|
||||||
@@ -30,6 +32,11 @@ TESTSPEC_RTEMS = pvdTestHarness.$(MUNCH_SUFFIX); pvDataAllTests
|
|||||||
# Build test scripts for hosts
|
# Build test scripts for hosts
|
||||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||||
|
|
||||||
|
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
|
||||||
|
TESTPROD = $(TESTPROD_HOST)
|
||||||
|
TESTSCRIPTS += $(TESTS:%=%.t)
|
||||||
|
endif
|
||||||
|
|
||||||
include $(TOP)/configure/RULES
|
include $(TOP)/configure/RULES
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -203,8 +203,8 @@ static void testCreateRequestInternal() {
|
|||||||
|
|
||||||
request = string("record[process=true,xxx=yyy]")
|
request = string("record[process=true,xxx=yyy]")
|
||||||
+ "putField(power.value)"
|
+ "putField(power.value)"
|
||||||
+ "getField(alarm,timeStamp,power{value,alarm},"
|
+ "getField(alarm,timeStamp,power{value,alarm},"
|
||||||
+ "current{value,alarm},voltage{value,alarm})";
|
+ "current{value,alarm},voltage{value,alarm})";
|
||||||
|
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
if(!pvRequest) { cout<< createRequest->getMessage() << endl;}
|
||||||
@@ -241,10 +241,10 @@ static void testCreateRequestInternal() {
|
|||||||
testPass("request %s",request.c_str());
|
testPass("request %s",request.c_str());
|
||||||
|
|
||||||
request = string("record[process=true,xxx=yyy]")
|
request = string("record[process=true,xxx=yyy]")
|
||||||
+ "putField(power.value)"
|
+ "putField(power.value)"
|
||||||
+ "getField(alarm,timeStamp,power{value,alarm},"
|
+ "getField(alarm,timeStamp,power{value,alarm},"
|
||||||
+ "current{value,alarm},voltage{value,alarm},"
|
+ "current{value,alarm},voltage{value,alarm},"
|
||||||
+ "ps0{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}},"
|
+ "ps0{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}},"
|
||||||
+ "ps1{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}}"
|
+ "ps1{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}}"
|
||||||
+ ")";
|
+ ")";
|
||||||
|
|
||||||
@@ -730,5 +730,3 @@ MAIN(testCreateRequest)
|
|||||||
testMaskErr();
|
testMaskErr();
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,16 +31,6 @@ void Unroller::unroll<0>(double /*d*/) {
|
|||||||
THROW_BASE_EXCEPTION("the root cause");
|
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() {
|
void testBaseExceptionTest() {
|
||||||
printf("testBaseException... ");
|
printf("testBaseException... ");
|
||||||
|
|
||||||
@@ -50,16 +40,6 @@ void testBaseExceptionTest() {
|
|||||||
printf("\n\n%s\n\n", be.what());
|
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");
|
testPass("testBaseException");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,4 +68,3 @@ MAIN(testBaseException)
|
|||||||
testBaseExceptionTest();
|
testBaseExceptionTest();
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,11 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
// allow to test deprecated functions without causing compiler warnings
|
||||||
|
#include <compilerDependencies.h>
|
||||||
|
#undef EPICS_DEPRECATED
|
||||||
|
#define EPICS_DEPRECATED
|
||||||
|
|
||||||
#include <testMain.h>
|
#include <testMain.h>
|
||||||
|
|
||||||
#include <pv/pvUnitTest.h>
|
#include <pv/pvUnitTest.h>
|
||||||
@@ -217,38 +222,6 @@ void testUnaligned()
|
|||||||
{
|
{
|
||||||
testDiag("test correctness of unaligned access");
|
testDiag("test correctness of unaligned access");
|
||||||
|
|
||||||
ByteBuffer buf(32, EPICS_ENDIAN_BIG);
|
|
||||||
|
|
||||||
// malloc() should give us a buffer aligned to at least native integer size
|
|
||||||
buf.align(sizeof(int));
|
|
||||||
testOk1(buf.getPosition()==0);
|
|
||||||
|
|
||||||
buf.clear();
|
|
||||||
buf.put<uint8>(0x42);
|
|
||||||
buf.put<uint16>(0x1020);
|
|
||||||
buf.align(2, '\x41');
|
|
||||||
testOk1(buf.getPosition()==4);
|
|
||||||
|
|
||||||
testOk1(memcmp(buf.getBuffer(), "\x42\x10\x20\x41", 4)==0);
|
|
||||||
|
|
||||||
buf.clear();
|
|
||||||
buf.put<uint8>(0x42);
|
|
||||||
buf.put<uint32>(0x12345678);
|
|
||||||
buf.align(4, '\x41');
|
|
||||||
testOk1(buf.getPosition()==8);
|
|
||||||
|
|
||||||
testOk1(memcmp(buf.getBuffer(), "\x42\x12\x34\x56\x78\x41\x41\x41", 8)==0);
|
|
||||||
|
|
||||||
buf.clear();
|
|
||||||
buf.put<uint8>(0x42);
|
|
||||||
uint64 val = 0x12345678;
|
|
||||||
val<<=32;
|
|
||||||
val |= 0x90abcdef;
|
|
||||||
buf.put<uint64>(val);
|
|
||||||
buf.align(8, '\x41');
|
|
||||||
testOk1(buf.getPosition()==16);
|
|
||||||
|
|
||||||
testOk1(memcmp(buf.getBuffer(), "\x42\x12\x34\x56\x78\x90\xab\xcd\xef\x41\x41\x41", 8)==0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@@ -305,7 +278,7 @@ void testArrayBE()
|
|||||||
|
|
||||||
MAIN(testByteBuffer)
|
MAIN(testByteBuffer)
|
||||||
{
|
{
|
||||||
testPlan(104);
|
testPlan(97);
|
||||||
testDiag("Tests byteBuffer");
|
testDiag("Tests byteBuffer");
|
||||||
testBasicOperations();
|
testBasicOperations();
|
||||||
testInverseEndianness(EPICS_ENDIAN_BIG, expect_be);
|
testInverseEndianness(EPICS_ENDIAN_BIG, expect_be);
|
||||||
|
|||||||
@@ -12,4 +12,3 @@ printf("EPICS_BYTE_ORDER: %s\n", (EPICS_BYTE_ORDER == EPICS_ENDIAN_LITTLE) ? "li
|
|||||||
printf("EPICS_FLOAT_WORD_ORDER: %s\n", (EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_LITTLE) ? "little" : "big");
|
printf("EPICS_FLOAT_WORD_ORDER: %s\n", (EPICS_FLOAT_WORD_ORDER == EPICS_ENDIAN_LITTLE) ? "little" : "big");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,4 +47,3 @@ MAIN(testEvent)
|
|||||||
testBasicEvent();
|
testBasicEvent();
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,4 +138,3 @@ MAIN(testOverrunBitSet)
|
|||||||
test();
|
test();
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,10 +67,6 @@ public:
|
|||||||
virtual void ensureBuffer(std::size_t /*size*/) {
|
virtual void ensureBuffer(std::size_t /*size*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void alignBuffer(std::size_t alignment) {
|
|
||||||
buffer->align(alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool directSerialize(ByteBuffer* /*existingBuffer*/, const char* /*toSerialize*/,
|
virtual bool directSerialize(ByteBuffer* /*existingBuffer*/, const char* /*toSerialize*/,
|
||||||
std::size_t /*elementCount*/, std::size_t /*elementSize*/)
|
std::size_t /*elementCount*/, std::size_t /*elementSize*/)
|
||||||
{
|
{
|
||||||
@@ -95,10 +91,6 @@ public:
|
|||||||
virtual void ensureData(size_t /*size*/) {
|
virtual void ensureData(size_t /*size*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void alignData(size_t alignment) {
|
|
||||||
buffer->align(alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool directDeserialize(ByteBuffer* /*existingBuffer*/, char* /*deserializeTo*/,
|
virtual bool directDeserialize(ByteBuffer* /*existingBuffer*/, char* /*deserializeTo*/,
|
||||||
std::size_t /*elementCount*/, std::size_t /*elementSize*/)
|
std::size_t /*elementCount*/, std::size_t /*elementSize*/)
|
||||||
{
|
{
|
||||||
@@ -146,46 +138,46 @@ void testEquals() {
|
|||||||
PVDataCreatePtr factory = getPVDataCreate();
|
PVDataCreatePtr factory = getPVDataCreate();
|
||||||
testOk1(factory.get()!=NULL);
|
testOk1(factory.get()!=NULL);
|
||||||
|
|
||||||
// be sure all is covered
|
// be sure all is covered
|
||||||
for (int i = pvBoolean; i < pvString; i++)
|
for (int i = pvBoolean; i < pvString; i++)
|
||||||
{
|
{
|
||||||
ScalarType scalarType = static_cast<ScalarType>(i);
|
ScalarType scalarType = static_cast<ScalarType>(i);
|
||||||
|
|
||||||
PVScalarPtr scalar1 = factory->createPVScalar(scalarType);
|
PVScalarPtr scalar1 = factory->createPVScalar(scalarType);
|
||||||
PVScalarPtr scalar2 = factory->createPVScalar(scalarType);
|
PVScalarPtr scalar2 = factory->createPVScalar(scalarType);
|
||||||
testOk1((*scalar1)==(*scalar2));
|
testOk1((*scalar1)==(*scalar2));
|
||||||
|
|
||||||
PVScalarArrayPtr array1 = factory->createPVScalarArray(scalarType);
|
PVScalarArrayPtr array1 = factory->createPVScalarArray(scalarType);
|
||||||
PVScalarArrayPtr array2 = factory->createPVScalarArray(scalarType);
|
PVScalarArrayPtr array2 = factory->createPVScalarArray(scalarType);
|
||||||
testOk1((*array1)==(*array2));
|
testOk1((*array1)==(*array2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// and a structure
|
// and a structure
|
||||||
PVStructurePtr structure1 = factory->createPVStructure(getStandardField()->timeStamp());
|
PVStructurePtr structure1 = factory->createPVStructure(getStandardField()->timeStamp());
|
||||||
PVStructurePtr structure2 = factory->createPVStructure(getStandardField()->timeStamp());
|
PVStructurePtr structure2 = factory->createPVStructure(getStandardField()->timeStamp());
|
||||||
testOk1((*structure1)==(*structure2));
|
testOk1((*structure1)==(*structure2));
|
||||||
|
|
||||||
// and a structure array
|
// and a structure array
|
||||||
PVStructureArrayPtr structureArray1 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure1->getStructure()));
|
PVStructureArrayPtr structureArray1 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure1->getStructure()));
|
||||||
PVStructureArrayPtr structureArray2 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure2->getStructure()));
|
PVStructureArrayPtr structureArray2 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure2->getStructure()));
|
||||||
testOk1((*structureArray1)==(*structureArray2));
|
testOk1((*structureArray1)==(*structureArray2));
|
||||||
|
|
||||||
// variant union
|
// variant union
|
||||||
PVUnionPtr variantUnion1 = factory->createPVVariantUnion();
|
PVUnionPtr variantUnion1 = factory->createPVVariantUnion();
|
||||||
PVUnionPtr variantUnion2 = factory->createPVVariantUnion();
|
PVUnionPtr variantUnion2 = factory->createPVVariantUnion();
|
||||||
testOk1((*variantUnion1)==(*variantUnion2));
|
testOk1((*variantUnion1)==(*variantUnion2));
|
||||||
|
|
||||||
variantUnion1->set(structure1);
|
variantUnion1->set(structure1);
|
||||||
variantUnion2->set(structure1);
|
variantUnion2->set(structure1);
|
||||||
testOk1((*variantUnion1)==(*variantUnion2));
|
testOk1((*variantUnion1)==(*variantUnion2));
|
||||||
|
|
||||||
variantUnion2->set(structureArray1);
|
variantUnion2->set(structureArray1);
|
||||||
testOk1((*variantUnion1)!=(*variantUnion2));
|
testOk1((*variantUnion1)!=(*variantUnion2));
|
||||||
|
|
||||||
// variant union array
|
// variant union array
|
||||||
PVUnionArrayPtr variantUnionArray1 = factory->createPVVariantUnionArray();
|
PVUnionArrayPtr variantUnionArray1 = factory->createPVVariantUnionArray();
|
||||||
PVUnionArrayPtr variantUnionArray2 = factory->createPVVariantUnionArray();
|
PVUnionArrayPtr variantUnionArray2 = factory->createPVVariantUnionArray();
|
||||||
testOk1((*variantUnionArray1)==(*variantUnionArray2));
|
testOk1((*variantUnionArray1)==(*variantUnionArray2));
|
||||||
|
|
||||||
// union
|
// union
|
||||||
UnionConstPtr punion = getFieldCreate()->createFieldBuilder()->
|
UnionConstPtr punion = getFieldCreate()->createFieldBuilder()->
|
||||||
@@ -198,30 +190,30 @@ void testEquals() {
|
|||||||
endNested()->
|
endNested()->
|
||||||
addArray("intArray", pvInt)->
|
addArray("intArray", pvInt)->
|
||||||
createUnion();
|
createUnion();
|
||||||
PVUnionPtr union1 = factory->createPVUnion(punion);
|
PVUnionPtr union1 = factory->createPVUnion(punion);
|
||||||
PVUnionPtr union2 = factory->createPVUnion(punion);
|
PVUnionPtr union2 = factory->createPVUnion(punion);
|
||||||
testOk1((*union1)==(*union2));
|
testOk1((*union1)==(*union2));
|
||||||
|
|
||||||
union1->select<PVDouble>("double")->put(1.2);
|
union1->select<PVDouble>("double")->put(1.2);
|
||||||
union2->select<PVDouble>("double")->put(1.2);
|
union2->select<PVDouble>("double")->put(1.2);
|
||||||
testOk1((*union1)==(*union2));
|
testOk1((*union1)==(*union2));
|
||||||
|
|
||||||
union2->select<PVDouble>("double")->put(2.2);
|
union2->select<PVDouble>("double")->put(2.2);
|
||||||
testOk1((*union1)!=(*union2));
|
testOk1((*union1)!=(*union2));
|
||||||
|
|
||||||
union2->select<PVDouble>("double2")->put(1.2);
|
union2->select<PVDouble>("double2")->put(1.2);
|
||||||
testOk1((*union1)!=(*union2));
|
testOk1((*union1)!=(*union2));
|
||||||
|
|
||||||
union2->select("nested");
|
union2->select("nested");
|
||||||
testOk1((*union1)!=(*union2));
|
testOk1((*union1)!=(*union2));
|
||||||
|
|
||||||
testOk1((*union1)!=(*variantUnion2));
|
testOk1((*union1)!=(*variantUnion2));
|
||||||
|
|
||||||
PVUnionArrayPtr unionArray1 = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
PVUnionArrayPtr unionArray1 = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
||||||
PVUnionArrayPtr unionArray2 = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
PVUnionArrayPtr unionArray2 = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
||||||
testOk1((*unionArray1)==(*unionArray2));
|
testOk1((*unionArray1)==(*unionArray2));
|
||||||
|
|
||||||
testOk1((*variantUnionArray1)!=(*unionArray2));
|
testOk1((*variantUnionArray1)!=(*unionArray2));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PVT>
|
template<typename PVT>
|
||||||
@@ -264,7 +256,7 @@ void testScalar() {
|
|||||||
|
|
||||||
testDiag("type %s", ScalarTypeFunc::name(pvBoolean));
|
testDiag("type %s", ScalarTypeFunc::name(pvBoolean));
|
||||||
PVBooleanPtr pvBoolean =
|
PVBooleanPtr pvBoolean =
|
||||||
std::tr1::static_pointer_cast<PVBoolean>(factory->createPVScalar(epics::pvData::pvBoolean));
|
std::tr1::static_pointer_cast<PVBoolean>(factory->createPVScalar(epics::pvData::pvBoolean));
|
||||||
pvBoolean->put(false);
|
pvBoolean->put(false);
|
||||||
serializationTest(pvBoolean);
|
serializationTest(pvBoolean);
|
||||||
pvBoolean->put(true);
|
pvBoolean->put(true);
|
||||||
@@ -284,7 +276,7 @@ void testScalar() {
|
|||||||
|
|
||||||
testDiag("type %s", ScalarTypeFunc::name(pvString));
|
testDiag("type %s", ScalarTypeFunc::name(pvString));
|
||||||
PVStringPtr pvString =
|
PVStringPtr pvString =
|
||||||
std::tr1::static_pointer_cast<PVString>(factory->createPVScalar(epics::pvData::pvString));
|
std::tr1::static_pointer_cast<PVString>(factory->createPVScalar(epics::pvData::pvString));
|
||||||
pvString->put("");
|
pvString->put("");
|
||||||
serializationTest(pvString);
|
serializationTest(pvString);
|
||||||
pvString->put("s");
|
pvString->put("s");
|
||||||
@@ -382,7 +374,7 @@ void testStructure() {
|
|||||||
testOk1(factory.get()!=NULL);
|
testOk1(factory.get()!=NULL);
|
||||||
|
|
||||||
testDiag("\tSimple structure serialization");
|
testDiag("\tSimple structure serialization");
|
||||||
PVStructurePtr pvStructure = factory->createPVStructure(getStandardField()->timeStamp());
|
PVStructurePtr pvStructure = factory->createPVStructure(getStandardField()->timeStamp());
|
||||||
pvStructure->getSubField<PVLong>("secondsPastEpoch")->put(123);
|
pvStructure->getSubField<PVLong>("secondsPastEpoch")->put(123);
|
||||||
pvStructure->getSubField<PVInt>("nanoseconds")->put(456);
|
pvStructure->getSubField<PVInt>("nanoseconds")->put(456);
|
||||||
pvStructure->getSubField<PVInt>("userTag")->put(789);
|
pvStructure->getSubField<PVInt>("userTag")->put(789);
|
||||||
@@ -390,11 +382,11 @@ void testStructure() {
|
|||||||
serializationTest(pvStructure);
|
serializationTest(pvStructure);
|
||||||
|
|
||||||
testDiag("\tComplex structure serialization");
|
testDiag("\tComplex structure serialization");
|
||||||
pvStructure = factory->createPVStructure(
|
pvStructure = factory->createPVStructure(
|
||||||
getStandardField()->structureArray(
|
getStandardField()->structureArray(
|
||||||
getStandardField()->timeStamp(), "alarm,control,display,timeStamp")
|
getStandardField()->timeStamp(), "alarm,control,display,timeStamp")
|
||||||
);
|
);
|
||||||
// TODO fill with data
|
// TODO fill with data
|
||||||
serializationTest(pvStructure);
|
serializationTest(pvStructure);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,7 +461,7 @@ void testUnion() {
|
|||||||
u = factory->createPVUnion(punion);
|
u = factory->createPVUnion(punion);
|
||||||
testOk1(NULL!=u.get());
|
testOk1(NULL!=u.get());
|
||||||
|
|
||||||
// null union test
|
// null union test
|
||||||
testOk1(NULL==u->get().get());
|
testOk1(NULL==u->get().get());
|
||||||
testOk1(PVUnion::UNDEFINED_INDEX == u->getSelectedIndex());
|
testOk1(PVUnion::UNDEFINED_INDEX == u->getSelectedIndex());
|
||||||
testOk1("" == u->getSelectedFieldName());
|
testOk1("" == u->getSelectedFieldName());
|
||||||
@@ -633,38 +625,38 @@ void serializationFieldTest(FieldConstPtr const & field)
|
|||||||
{
|
{
|
||||||
testShow()<<CURRENT_FUNCTION<<"\n"<<field;
|
testShow()<<CURRENT_FUNCTION<<"\n"<<field;
|
||||||
|
|
||||||
buffer->clear();
|
buffer->clear();
|
||||||
|
|
||||||
// serialize
|
// serialize
|
||||||
field->serialize(buffer, flusher);
|
field->serialize(buffer, flusher);
|
||||||
|
|
||||||
// deserialize
|
// deserialize
|
||||||
buffer->flip();
|
buffer->flip();
|
||||||
|
|
||||||
FieldConstPtr deserializedField = getFieldCreate()->deserialize(buffer, control);
|
FieldConstPtr deserializedField = getFieldCreate()->deserialize(buffer, control);
|
||||||
|
|
||||||
testShow()<<" after "<<(void*)field.get()<<" == "<<(void*)deserializedField.get();
|
testShow()<<" after "<<(void*)field.get()<<" == "<<(void*)deserializedField.get();
|
||||||
testOk1(*field == *deserializedField);
|
testOk1(*field == *deserializedField);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testIntrospectionSerialization()
|
void testIntrospectionSerialization()
|
||||||
{
|
{
|
||||||
testDiag("Testing introspection serialization...");
|
testDiag("Testing introspection serialization...");
|
||||||
|
|
||||||
FieldCreatePtr factory = getFieldCreate();
|
FieldCreatePtr factory = getFieldCreate();
|
||||||
testOk1(factory.get()!=NULL);
|
testOk1(factory.get()!=NULL);
|
||||||
|
|
||||||
// be sure all is covered
|
// be sure all is covered
|
||||||
for (int i = pvBoolean; i < pvString; i++)
|
for (int i = pvBoolean; i < pvString; i++)
|
||||||
{
|
{
|
||||||
ScalarType scalarType = static_cast<ScalarType>(i);
|
ScalarType scalarType = static_cast<ScalarType>(i);
|
||||||
|
|
||||||
ScalarConstPtr scalar = factory->createScalar(scalarType);
|
ScalarConstPtr scalar = factory->createScalar(scalarType);
|
||||||
serializationFieldTest(scalar);
|
serializationFieldTest(scalar);
|
||||||
|
|
||||||
ScalarArrayConstPtr array = factory->createScalarArray(scalarType);
|
ScalarArrayConstPtr array = factory->createScalarArray(scalarType);
|
||||||
serializationFieldTest(array);
|
serializationFieldTest(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
// and a structure
|
// and a structure
|
||||||
StructureConstPtr structure = getStandardField()->timeStamp();
|
StructureConstPtr structure = getStandardField()->timeStamp();
|
||||||
@@ -748,7 +740,7 @@ void testBoundedString() {
|
|||||||
try {
|
try {
|
||||||
pvStr->put("tooLargeString");
|
pvStr->put("tooLargeString");
|
||||||
testFail("too large string accepted");
|
testFail("too large string accepted");
|
||||||
} catch (std::overflow_error oe) {
|
} catch (std::overflow_error& oe) {
|
||||||
// OK
|
// OK
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,4 +886,3 @@ MAIN(testSerialization) {
|
|||||||
|
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -474,6 +474,9 @@ void testVectorConvert()
|
|||||||
testOk1(ints.unique());
|
testOk1(ints.unique());
|
||||||
testOk1(strings.size()==ints.size());
|
testOk1(strings.size()==ints.size());
|
||||||
testOk1(strings.at(0)=="42");
|
testOk1(strings.at(0)=="42");
|
||||||
|
|
||||||
|
testDiag("convert empty array");
|
||||||
|
testOk1(pvd::shared_vector_convert<double>(pvd::shared_vector<pvd::int32>()).empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testWeak()
|
void testWeak()
|
||||||
@@ -695,7 +698,7 @@ void testCXX11Init()
|
|||||||
|
|
||||||
MAIN(testSharedVector)
|
MAIN(testSharedVector)
|
||||||
{
|
{
|
||||||
testPlan(191);
|
testPlan(192);
|
||||||
testDiag("Tests for shared_vector");
|
testDiag("Tests for shared_vector");
|
||||||
|
|
||||||
testDiag("sizeof(shared_vector<pvd::int32>)=%lu",
|
testDiag("sizeof(shared_vector<pvd::int32>)=%lu",
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
|
|
||||||
#include <pv/pvdVersion.h>
|
#include <pv/pvdVersion.h>
|
||||||
|
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
|
||||||
|
|
||||||
#include <pv/json.h>
|
#include <pv/json.h>
|
||||||
#include <pv/bitSet.h>
|
#include <pv/bitSet.h>
|
||||||
#include <pv/valueBuilder.h>
|
#include <pv/valueBuilder.h>
|
||||||
@@ -125,7 +123,7 @@ const char bigtest[] =
|
|||||||
" ,{\"a\":9, \"b\":10}\n"
|
" ,{\"a\":9, \"b\":10}\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
" \"any\": \"4.2\",\n"
|
" \"any\": \"4.2\",\n"
|
||||||
" \"almost\": \"hello\"\n"
|
" \"almost\": \"long string /with\\\\ several \\\" and ' characters\\u001f\\u2705\"\n"
|
||||||
"}";
|
"}";
|
||||||
// intentionally not setting "extra"
|
// intentionally not setting "extra"
|
||||||
|
|
||||||
@@ -206,7 +204,7 @@ void testInto()
|
|||||||
}
|
}
|
||||||
|
|
||||||
testFieldEqual<pvd::PVString>(val, "any", "4.2");
|
testFieldEqual<pvd::PVString>(val, "any", "4.2");
|
||||||
testFieldEqual<pvd::PVString>(val, "almost", "hello");
|
testFieldEqual<pvd::PVString>(val, "almost", "long string /with\\ several \" and ' characters\x1f\xe2\x9c\x85");
|
||||||
}
|
}
|
||||||
|
|
||||||
void testroundtrip()
|
void testroundtrip()
|
||||||
@@ -257,19 +255,19 @@ void testroundtrip()
|
|||||||
round2 = strm.str();
|
round2 = strm.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
testEqual(round2, "{\"scalar\": 42,"
|
testEqual(round2, "{\"scalar\":42,"
|
||||||
"\"ivec\": [1,2,3],"
|
"\"ivec\":[1,2,3],"
|
||||||
"\"svec\": [\"one\",\"two\"],"
|
"\"svec\":[\"one\",\"two\"],"
|
||||||
"\"sub\": {"
|
"\"sub\":{"
|
||||||
"\"x\": {"
|
"\"x\":{"
|
||||||
"\"y\": 43"
|
"\"y\":43"
|
||||||
"}},"
|
"}},"
|
||||||
"\"extra\": 0,"
|
"\"extra\":0,"
|
||||||
"\"sarr\": [{\"a\": 5,\"b\": 6},"
|
"\"sarr\":[{\"a\":5,\"b\":6},"
|
||||||
"{\"a\": 7,\"b\": 8},"
|
"{\"a\":7,\"b\":8},"
|
||||||
"{\"a\": 9,\"b\": 10}],"
|
"{\"a\":9,\"b\":10}],"
|
||||||
"\"any\": \"4.2\","
|
"\"any\":\"4.2\","
|
||||||
"\"almost\": \"hello\""
|
"\"almost\":\"long string /with\\\\ several \\\" and ' characters\\u001F\xe2\x9c\x85\""
|
||||||
"}");
|
"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,15 +288,3 @@ MAIN(testjson)
|
|||||||
}
|
}
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // EPICS_VERSION_INT
|
|
||||||
|
|
||||||
#include <epicsUnitTest.h>
|
|
||||||
|
|
||||||
MAIN(testjson)
|
|
||||||
{
|
|
||||||
testPlan(1);
|
|
||||||
testSkip(1, "JSON parser requires Base >=3.15.0.1");
|
|
||||||
return testDone();
|
|
||||||
}
|
|
||||||
#endif //EPICS_VERSION_INT
|
|
||||||
|
|||||||
@@ -16,10 +16,6 @@
|
|||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/standardField.h>
|
#include <pv/standardField.h>
|
||||||
|
|
||||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
|
||||||
# define USE_JSON
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace pvd = epics::pvData;
|
namespace pvd = epics::pvData;
|
||||||
|
|
||||||
typedef std::vector<std::string> lines_t;
|
typedef std::vector<std::string> lines_t;
|
||||||
@@ -138,12 +134,12 @@ void showNTScalarNumeric()
|
|||||||
{
|
{
|
||||||
testDiag("%s", CURRENT_FUNCTION);
|
testDiag("%s", CURRENT_FUNCTION);
|
||||||
pvd::PVStructurePtr input(pvd::getPVDataCreate()->createPVStructure(scalarNumeric));
|
pvd::PVStructurePtr input(pvd::getPVDataCreate()->createPVStructure(scalarNumeric));
|
||||||
input->getSubFieldT<pvd::PVScalar>("value")->putFrom(-42);
|
input->getSubFieldT<pvd::PVScalar>("value")->putFrom(pvd::int32(-42));
|
||||||
|
|
||||||
testDiff("<undefined> -42 \n", print(input->stream()));
|
testDiff("<undefined> -42 \n", print(input->stream()));
|
||||||
|
|
||||||
input->getSubFieldT<pvd::PVScalar>("alarm.severity")->putFrom(1);
|
input->getSubFieldT<pvd::PVScalar>("alarm.severity")->putFrom(pvd::int32(1));
|
||||||
input->getSubFieldT<pvd::PVScalar>("alarm.status")->putFrom(1);
|
input->getSubFieldT<pvd::PVScalar>("alarm.status")->putFrom(pvd::int32(1));
|
||||||
input->getSubFieldT<pvd::PVString>("alarm.message")->put("FOO");
|
input->getSubFieldT<pvd::PVString>("alarm.message")->put("FOO");
|
||||||
|
|
||||||
testDiff("<undefined> -42 MINOR DEVICE FOO \n", print(input->stream()));
|
testDiff("<undefined> -42 MINOR DEVICE FOO \n", print(input->stream()));
|
||||||
@@ -166,8 +162,8 @@ void showNTScalarString()
|
|||||||
|
|
||||||
testDiff("<undefined> bar \n", print(input->stream()));
|
testDiff("<undefined> bar \n", print(input->stream()));
|
||||||
|
|
||||||
input->getSubFieldT<pvd::PVScalar>("alarm.severity")->putFrom(1);
|
input->getSubFieldT<pvd::PVScalar>("alarm.severity")->putFrom(pvd::int32(1));
|
||||||
input->getSubFieldT<pvd::PVScalar>("alarm.status")->putFrom(1);
|
input->getSubFieldT<pvd::PVScalar>("alarm.status")->putFrom(pvd::int32(1));
|
||||||
input->getSubFieldT<pvd::PVString>("alarm.message")->put("FOO");
|
input->getSubFieldT<pvd::PVString>("alarm.message")->put("FOO");
|
||||||
|
|
||||||
testDiff("<undefined> bar MINOR DEVICE FOO \n", print(input->stream()));
|
testDiff("<undefined> bar MINOR DEVICE FOO \n", print(input->stream()));
|
||||||
@@ -201,12 +197,12 @@ void showNTEnum()
|
|||||||
|
|
||||||
input->getSubFieldT<pvd::PVInt>("value.index")->put(1);
|
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"
|
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"
|
" int index 1\n"
|
||||||
" string[] choices [\"one\", \"a two\"]\n"
|
" string[] choices [one, \"a two\"]\n"
|
||||||
" alarm_t alarm \n"
|
" alarm_t alarm \n"
|
||||||
" int severity 0\n"
|
" int severity 0\n"
|
||||||
" int status 0\n"
|
" int status 0\n"
|
||||||
@@ -251,7 +247,7 @@ void showNTTable()
|
|||||||
iarr.push_back(42); // will not be shown
|
iarr.push_back(42); // will not be shown
|
||||||
input->getSubFieldT<pvd::PVIntArray>("value.colA")->replace(pvd::freeze(iarr));
|
input->getSubFieldT<pvd::PVIntArray>("value.colA")->replace(pvd::freeze(iarr));
|
||||||
|
|
||||||
sarr.push_back("one\x7f");
|
sarr.push_back("one\x7f\x80");
|
||||||
sarr.push_back("two words");
|
sarr.push_back("two words");
|
||||||
sarr.push_back("A '\"'");
|
sarr.push_back("A '\"'");
|
||||||
input->getSubFieldT<pvd::PVStringArray>("value.colB")->replace(pvd::freeze(sarr));
|
input->getSubFieldT<pvd::PVStringArray>("value.colB")->replace(pvd::freeze(sarr));
|
||||||
@@ -259,7 +255,7 @@ void showNTTable()
|
|||||||
|
|
||||||
testDiff("<undefined> \n"
|
testDiff("<undefined> \n"
|
||||||
"labelA \"label B\"\n"
|
"labelA \"label B\"\n"
|
||||||
" 1 one\\x7F\n"
|
" 1 one\\x7F\\x80\n"
|
||||||
" 2 \"two words\"\n"
|
" 2 \"two words\"\n"
|
||||||
" 3 \"A \\'\"\"\\'\"\n"
|
" 3 \"A \\'\"\"\\'\"\n"
|
||||||
, print(input->stream()),
|
, print(input->stream()),
|
||||||
@@ -303,7 +299,7 @@ void testRaw()
|
|||||||
|
|
||||||
testDiff("omg \n"
|
testDiff("omg \n"
|
||||||
" string scalar \n" // bit 1
|
" string scalar \n" // bit 1
|
||||||
" string[] scalarArray [\"hello\", \"world\\x7F\"]\n"
|
" string[] scalarArray [hello, \"world\\x7F\"]\n"
|
||||||
" structure below\n"
|
" structure below\n"
|
||||||
" int A 0\n" // bit 4
|
" int A 0\n" // bit 4
|
||||||
" union select\n"
|
" union select\n"
|
||||||
@@ -323,7 +319,7 @@ void testRaw()
|
|||||||
|
|
||||||
testDiff("omg \n"
|
testDiff("omg \n"
|
||||||
"\033[1m string scalar \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[0m structure below\n"
|
||||||
"\033[1m int A 0\n"
|
"\033[1m int A 0\n"
|
||||||
"\033[0m union select\n"
|
"\033[0m union select\n"
|
||||||
@@ -351,13 +347,20 @@ void testEscape()
|
|||||||
testEqual("hello\"\"world", std::string(SB()<<pvd::escape("hello\"world").style(pvd::escape::CSV)));
|
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", 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
|
} // namespace
|
||||||
|
|
||||||
MAIN(testprinter)
|
MAIN(testprinter)
|
||||||
{
|
{
|
||||||
testPlan(20);
|
testPlan(26);
|
||||||
showNTScalarNumeric();
|
showNTScalarNumeric();
|
||||||
showNTScalarString();
|
showNTScalarString();
|
||||||
showNTEnum();
|
showNTEnum();
|
||||||
|
|||||||
@@ -232,4 +232,3 @@ MAIN(testProperty)
|
|||||||
printRecords();
|
printRecords();
|
||||||
return testDone();;
|
return testDone();;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <testMain.h>
|
#include <testMain.h>
|
||||||
#include <epicsUnitTest.h>
|
#include <epicsUnitTest.h>
|
||||||
|
#include <epicsStdio.h>
|
||||||
|
|
||||||
#include <pv/current_function.h>
|
#include <pv/current_function.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
@@ -54,7 +55,7 @@ void buildMiss()
|
|||||||
for(size_t i=0; i<1000; i++) {
|
for(size_t i=0; i<1000; i++) {
|
||||||
// unique name each time to (partially) defeat caching
|
// unique name each time to (partially) defeat caching
|
||||||
char buf[10];
|
char buf[10];
|
||||||
sprintf(buf, "field%zu", i);
|
epicsSnprintf(buf, sizeof(buf), "field%lu", (unsigned long) i);
|
||||||
|
|
||||||
record.start();
|
record.start();
|
||||||
|
|
||||||
|
|||||||
@@ -127,4 +127,3 @@ MAIN(testBitSetUtil)
|
|||||||
test();
|
test();
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ void test_factory()
|
|||||||
testOk1(fb.get() != 0);
|
testOk1(fb.get() != 0);
|
||||||
|
|
||||||
FieldBuilderPtr fb2 = fieldCreate->createFieldBuilder();
|
FieldBuilderPtr fb2 = fieldCreate->createFieldBuilder();
|
||||||
testOk1(fb.get() != fb2.get());
|
testOk1(fb.get() != fb2.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_structure()
|
void test_structure()
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ MAIN(testOperators)
|
|||||||
PVDoublePtr pvValue = pvStructure->getSubField<PVDouble>("value");
|
PVDoublePtr pvValue = pvStructure->getSubField<PVDouble>("value");
|
||||||
*pvValue <<= testDV;
|
*pvValue <<= testDV;
|
||||||
|
|
||||||
double dv;
|
double dv = 0.;
|
||||||
*pvValue >>= dv;
|
*pvValue >>= dv;
|
||||||
testOk1(testDV == dv);
|
testOk1(testDV == dv);
|
||||||
|
|
||||||
@@ -95,4 +95,3 @@ MAIN(testOperators)
|
|||||||
|
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,34 @@ static string alarmTimeStamp("alarm,timeStamp");
|
|||||||
static string alarmTimeStampValueAlarm("alarm,timeStamp,valueAlarm");
|
static string alarmTimeStampValueAlarm("alarm,timeStamp,valueAlarm");
|
||||||
static string allProperties("alarm,timeStamp,display,control,valueAlarm");
|
static string allProperties("alarm,timeStamp,display,control,valueAlarm");
|
||||||
|
|
||||||
|
static void testSizes()
|
||||||
|
{
|
||||||
|
#define SHOW(T) testDiag("sizeof(" #T ")==%zu", sizeof(T))
|
||||||
|
SHOW(std::string);
|
||||||
|
SHOW(std::vector<int>);
|
||||||
|
SHOW(shared_vector<int>);
|
||||||
|
SHOW(std::tr1::shared_ptr<PVField>);
|
||||||
|
SHOW(Field);
|
||||||
|
SHOW(Structure);
|
||||||
|
SHOW(StructureArray);
|
||||||
|
SHOW(Union);
|
||||||
|
SHOW(UnionArray);
|
||||||
|
SHOW(Scalar);
|
||||||
|
SHOW(ScalarArray);
|
||||||
|
SHOW(PVField);
|
||||||
|
SHOW(PVStructure);
|
||||||
|
SHOW(PVStructureArray);
|
||||||
|
SHOW(PVUnion);
|
||||||
|
SHOW(PVUnionArray);
|
||||||
|
SHOW(PVScalar);
|
||||||
|
SHOW(PVScalarArray);
|
||||||
|
SHOW(PVInt);
|
||||||
|
SHOW(PVIntArray);
|
||||||
|
SHOW(PVString);
|
||||||
|
SHOW(PVStringArray);
|
||||||
|
#undef SHOW
|
||||||
|
}
|
||||||
|
|
||||||
static void testCreatePVStructure()
|
static void testCreatePVStructure()
|
||||||
{
|
{
|
||||||
PVStructurePtr pv0 = standardPVField->scalar(
|
PVStructurePtr pv0 = standardPVField->scalar(
|
||||||
@@ -747,6 +775,7 @@ MAIN(testPVData)
|
|||||||
standardField = getStandardField();
|
standardField = getStandardField();
|
||||||
standardPVField = getStandardPVField();
|
standardPVField = getStandardPVField();
|
||||||
convert = getConvert();
|
convert = getConvert();
|
||||||
|
testSizes();
|
||||||
testCreatePVStructure();
|
testCreatePVStructure();
|
||||||
testCreatePVStructureWithInvalidName();
|
testCreatePVStructureWithInvalidName();
|
||||||
testPVScalar();
|
testPVScalar();
|
||||||
@@ -762,4 +791,3 @@ MAIN(testPVData)
|
|||||||
}
|
}
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,4 +64,3 @@ MAIN(testPVType)
|
|||||||
printf("PASSED\n");
|
printf("PASSED\n");
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -203,4 +203,3 @@ MAIN(testPVUnion)
|
|||||||
testClearUnion();
|
testClearUnion();
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,4 +68,3 @@ MAIN(testStandardField)
|
|||||||
testPass("testStandardField");
|
testPass("testStandardField");
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,4 +73,3 @@ MAIN(testStandardPVField)
|
|||||||
testPass("testStandardPVField");
|
testPass("testStandardPVField");
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
testApp/rtemsTestData.c
Normal file
2
testApp/rtemsTestData.c
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/* no test data */
|
||||||
|
const void* epicsRtemsFSImage = 0;
|
||||||
Reference in New Issue
Block a user