This is Unofficial EPICS BASE Doxygen Site
print.cpp
Go to the documentation of this file.
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 
6 #include <vector>
7 #include <sstream>
8 
9 #define epicsExportSharedSymbols
10 #include <pv/pvdVersion.h>
11 #include <pv/pvData.h>
12 #include <pv/valueBuilder.h>
13 #include <pv/bitSet.h>
14 #include "pv/json.h"
15 
16 namespace pvd = epics::pvData;
17 
18 namespace {
19 
20 struct args {
21  std::ostream& strm;
22  const pvd::JSONPrintOptions& opts;
23 
24  unsigned indent;
25 
26  args(std::ostream& strm,
27  const pvd::JSONPrintOptions& opts)
28  :strm(strm)
29  ,opts(opts)
30  ,indent(opts.indent)
31  {}
32 
33  void doIntent() {
34  if(!opts.multiLine) return;
35  strm.put('\n');
36  unsigned i=indent;
37  while(i--) strm.put(' ');
38  }
39 };
40 
41 void show_field(args& A, const pvd::PVField* fld, const pvd::BitSet *mask);
42 
43 void show_struct(args& A, const pvd::PVStructure* fld, const pvd::BitSet *mask)
44 {
46  const pvd::PVFieldPtrArray& children = fld->getPVFields();
47 
48  const pvd::StringArray& names = type->getFieldNames();
49 
50  A.strm.put('{');
51  A.indent++;
52 
53  bool first = true;
54  for(size_t i=0, N=names.size(); i<N; i++)
55  {
56  if(mask && !mask->get(children[i]->getFieldOffset())) continue;
57 
58  if(first)
59  first = false;
60  else
61  A.strm.put(',');
62  A.doIntent();
63  A.strm<<'\"'<<names[i]<<"\": ";
64  show_field(A, children[i].get(), mask);
65  }
66 
67  A.indent--;
68  A.doIntent();
69  A.strm.put('}');
70 }
71 
72 void show_field(args& A, const pvd::PVField* fld, const pvd::BitSet *mask)
73 {
74  switch(fld->getField()->getType())
75  {
76  case pvd::scalar:
77  {
78  const pvd::PVScalar *scalar=static_cast<const pvd::PVScalar*>(fld);
79  if(scalar->getScalar()->getScalarType()==pvd::pvString) {
80  A.strm<<'\"'<<scalar->getAs<std::string>()<<'\"';
81  } else {
82  A.strm<<scalar->getAs<std::string>();
83  }
84  }
85  return;
86  case pvd::scalarArray:
87  {
88  const pvd::PVScalarArray *scalar=static_cast<const pvd::PVScalarArray*>(fld);
89  const bool isstring = scalar->getScalarArray()->getElementType()==pvd::pvString;
90 
92  scalar->getAs<void>(arr);
93 
94  pvd::shared_vector<const std::string> sarr(pvd::shared_vector_convert<const std::string>(arr));
95 
96  A.strm.put('[');
97  for(size_t i=0, N=sarr.size(); i<N; i++) {
98  if(i!=0)
99  A.strm.put(',');
100  if(isstring)
101  A.strm.put('\"');
102  A.strm<<sarr[i];
103  if(isstring)
104  A.strm.put('\"');
105  }
106  A.strm.put(']');
107  }
108  return;
109  case pvd::structure:
110  show_struct(A, static_cast<const pvd::PVStructure*>(fld), mask);
111  return;
112  case pvd::structureArray:
113  {
114  pvd::PVStructureArray::const_svector arr(static_cast<const pvd::PVStructureArray*>(fld)->view());
115  A.strm.put('[');
116  A.indent++;
117 
118  for(size_t i=0, N=arr.size(); i<N; i++) {
119  if(i!=0)
120  A.strm.put(',');
121  A.doIntent();
122  if(arr[i])
123  show_struct(A, arr[i].get(), 0);
124  else
125  A.strm<<"NULL";
126  }
127 
128  A.indent--;
129  A.doIntent();
130  A.strm.put(']');
131  }
132  return;
133  case pvd::union_:
134  {
135  const pvd::PVUnion *U=static_cast<const pvd::PVUnion*>(fld);
136  const pvd::PVField::const_shared_pointer& C(U->get());
137 
138  if(!C) {
139  A.strm<<"null";
140  } else {
141  show_field(A, C.get(), 0);
142  }
143  }
144  return;
145  case pvd::unionArray: {
146  const pvd::PVUnionArray *U=static_cast<const pvd::PVUnionArray*>(fld);
148  A.strm.put('[');
149  A.indent++;
150 
151  for(size_t i=0, N=arr.size(); i<N; i++) {
152  if(i!=0)
153  A.strm.put(',');
154  A.doIntent();
155  if(arr[i])
156  show_field(A, arr[i].get(), 0);
157  else
158  A.strm<<"NULL";
159  }
160 
161  A.indent--;
162  A.doIntent();
163  A.strm.put(']');
164 
165  }
166  return;
167  }
168  // should not be reached
169  if(A.opts.ignoreUnprintable)
170  A.strm<<"// unprintable field type";
171  else
172  throw std::runtime_error("Encountered unprintable field type");
173 }
174 
175 void expandBS(const pvd::PVStructure& top, pvd::BitSet& mask, bool parents) {
176  if(mask.get(0)) { // special handling because getSubField(0) not allowed
177  // wildcard
178  for(size_t idx=1, N=top.getNumberFields(); idx<N; idx++) {
179  mask.set(idx);
180  }
181 
182  } else {
183  for(pvd::int32 idx = mask.nextSetBit(0), N=top.getNumberFields(); idx>=0 && idx<N; idx=mask.nextSetBit(idx+1)) {
184  pvd::PVField::const_shared_pointer fld = top.getSubFieldT(idx);
185 
186  // look forward and mark all children
187  for(size_t i=idx+1, N=fld->getNextFieldOffset(); i<N; i++)
188  mask.set(i);
189 
190  if(parents) {
191  // look back and mark all parents
192  // we've already stepped past all parents so siblings will not be automatically marked
193  for(const pvd::PVStructure *parent = fld->getParent(); parent; parent = parent->getParent()) {
194  mask.set(parent->getFieldOffset());
195  }
196  }
197  }
198  }
199 }
200 
201 } // namespace
202 
203 namespace epics{namespace pvData{
204 
206  :multiLine(true)
207  ,ignoreUnprintable(true)
208  ,indent(0)
209 {}
210 
211 void printJSON(std::ostream& strm,
212  const PVStructure& val,
213  const BitSet& mask,
214  const JSONPrintOptions& opts)
215 {
216  args A(strm, opts);
217  pvd::BitSet emask(mask);
218  expandBS(val, emask, true);
219  if(!emask.get(0)) return;
220  show_struct(A, &val, &emask);
221 }
222 
223 void printJSON(std::ostream& strm,
224  const PVField& val,
225  const JSONPrintOptions& opts)
226 {
227  args A(strm, opts);
228  show_field(A, &val, 0);
229 }
230 
231 }} // namespace epics::pvData
const PVFieldPtrArray & getPVFields() const
Definition: pvData.h:736
const PVFieldPtr & get()
Definition: pvData.h:968
PVScalar is the base class for each scalar field.
Definition: pvData.h:272
Data class for a unionArray.
Definition: pvData.h:1335
bool get(uint32 bitIndex) const
Definition: bitSet.cpp:130
#define true
Definition: flexdef.h:84
int i
Definition: scan.c:967
const FieldConstPtr & getField() const
Definition: pvData.h:208
pvd::StructureConstPtr type
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
std::tr1::shared_ptr< const Structure > StructureConstPtr
Definition: pvIntrospect.h:162
::epics::pvData::shared_vector< const PVStructurePtr > const_svector
Definition: pvData.h:1249
Options used during printing.
Definition: json.h:42
A vector of bits.
Definition: bitSet.h:56
PVField is the base class for each PVData field.
Definition: pvData.h:152
unsigned indent
Initial indentation (# of spaces)
Definition: json.h:46
const ScalarConstPtr getScalar() const
Definition: PVScalar.cpp:27
void getAs(shared_vector< const T > &out) const
Definition: pvData.h:647
pvData
Definition: monitor.h:428
Base class for a scalarArray.
Definition: pvData.h:618
int32 nextSetBit(uint32 fromIndex) const
Definition: bitSet.cpp:164
PVUnion has a single subfield.
Definition: pvData.h:940
void printJSON(std::ostream &strm, const PVStructure &val, const BitSet &mask, const JSONPrintOptions &opts)
Definition: print.cpp:211
const ScalarArrayConstPtr getScalarArray() const
std::vector< PVFieldPtr > PVFieldPtrArray
Definition: pvData.h:70
Data interface for a structure,.
Definition: pvData.h:712
FORCE_INLINE std::tr1::shared_ptr< PVField > getSubFieldT(A a)
Definition: pvData.h:786
std::vector< std::string > StringArray
Definition: pvType.h:110
const StructureConstPtr & getStructure() const
Definition: pvData.h:731
virtual const_svector view() const OVERRIDE
Fetch a read-only view of the current array data.
Definition: pvData.h:1396
BitSet & set(uint32 bitIndex)
Definition: bitSet.cpp:103
PVStructure * getParent()
Definition: pvData.h:213
T getAs() const
Definition: pvData.h:302
bool multiLine
include new lines
Definition: json.h:44
int32_t int32
Definition: pvType.h:83
::epics::pvData::shared_vector< const PVUnionPtr > const_svector
Definition: pvData.h:1348
std::size_t getNumberFields() const
Definition: PVField.cpp:56