added pvArray.html; made queue.h and bitSetUtil.* compatible with pvDataCPP.
This commit is contained in:
998
documentation/pvArray.html
Normal file
998
documentation/pvArray.html
Normal file
@@ -0,0 +1,998 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<title>EPICS pvArray</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
||||
<style type="text/css">
|
||||
/*<![CDATA[*/
|
||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
||||
table { margin-left: auto; margin-right: auto }
|
||||
.diagram { text-align: center; margin: 2.5em 0 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="head">
|
||||
<h1>EPICS Array</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 13-Jun-2013</h2>
|
||||
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvArray.html">pvArray.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd>none</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd>None</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL<br />
|
||||
Michael Davidsaver, BNL</dd>
|
||||
</dl>
|
||||
|
||||
<p class="copyright">This product is made available subject to acceptance of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/LICENSE.html">EPICS open source
|
||||
license.</a></p>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
|
||||
<div id="toc">
|
||||
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
|
||||
</div>
|
||||
<div id="contents" class="contents">
|
||||
|
||||
|
||||
<h2>Introduction</h2>
|
||||
<p>This is the documentation for the scalarArray data type as defined by pvDataCPP-md.
|
||||
When complete it will be merged into pvDataCPP.html.
|
||||
Only sharedVector is currently documented.
|
||||
It is documented in the next section, but when merged into pvDataCPP.html,
|
||||
will appear in a later section.
|
||||
For now ignore the documentation in pvDataApp/pv.</p>
|
||||
<p>When <b>NOTE EXISTING</b> appears it means that there is a question about
|
||||
the existing shared_vector implementation.</p>
|
||||
|
||||
<h2>shared_vector</h2>
|
||||
<h3>Status</h3>
|
||||
<p>I think that all public components of sharedVector.h
|
||||
are now documented, but not all have a description or example.
|
||||
Thus the documentation needs more work.
|
||||
</p>
|
||||
<h3>Introduction</h3>
|
||||
<p>A shared_vector is a container as defined by the C++ standard library.
|
||||
It is like std::vector but provides two additional features
|
||||
1) shared raw array and 2) a window into the raw array.</p>
|
||||
<p>To support these two features a shared_vector keeps the following
|
||||
private data:
|
||||
<dl>
|
||||
<dt>m_data</dt>
|
||||
<dd>This is a std::tr1::shared_ptr for the actual data array.
|
||||
</dd>
|
||||
<dt>m_offset</dt>
|
||||
<dd>This is the offset of the first element seen by the window.</dd>
|
||||
<dt>m_count</dt>
|
||||
<dd>This is the size, i. e. total number of elements, seen by the window.</dd>
|
||||
<dt>m_total</dt>
|
||||
<dd>This is the number of elements between offset and the end of the array referenced
|
||||
by m_data.</dd>
|
||||
</dl>
|
||||
Note that only m_data is shared. Thus each shared_vector has it's own window.</p>
|
||||
<p>The following subsections are organized as follows:
|
||||
<dl>
|
||||
<dt>shared_vector example</dt>
|
||||
<dd>The example code is based on a shared_vector<int32>
|
||||
This subsection show the C++ definitions that are assumed by
|
||||
the example code.
|
||||
The source that contains the example code will be part
|
||||
of this project but not yet.</dd>
|
||||
<dt>std::vector compatible subsections</dt>
|
||||
<dd>The types and methods that have the same names as std::vector.</dd>
|
||||
<dt>share_vector specific</dt>
|
||||
<dd>The methods that are not part of std::vector.</dd>
|
||||
</dl></p>
|
||||
<p>The subsections that are compatible with std::vector are organized
|
||||
and start with a brief summary modeled after Section 31.3(STL Containers) in:<br />
|
||||
"The C++ Programming Language, C++11, Fourth Edition", Bjarne Stroustrup,2013<br/>
|
||||
The subsection names are the same names that Stroustrup uses.
|
||||
Each subsection starts with a brief summary that is similar to
|
||||
the summary Stroustrup has at the beginnining of each subsection.</p>
|
||||
<p>The comparison is always with std::vector.
|
||||
In addition it shows what is defined by by std::vector but not by
|
||||
shared_vector.</p>
|
||||
<p>Someone who already understand the C++ STL can understand shared_vector
|
||||
by just looking at the brief summarys.
|
||||
For others the brief summary is followed by tutorial information.
|
||||
</p>
|
||||
<h3>shared_vector example</h3>
|
||||
<p>The examples all assume that the following has been defined:</p>
|
||||
<pre>
|
||||
typedef shared_vector<int32> Int32Array;
|
||||
...
|
||||
static void dumpArray(String const &message,Int32Array const& int32Array);
|
||||
</pre>
|
||||
<p>The following:
|
||||
<pre>
|
||||
Int32Array int32Array(5);
|
||||
dumpArray("example",int32Array);
|
||||
</pre>
|
||||
creates a shared vector that holds an array of five elements where each element is a
|
||||
32 bit signed integer.
|
||||
The call to dumpArray displays the message and the array elements on standard out:
|
||||
<pre>
|
||||
example 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
</pre>
|
||||
</p>
|
||||
<p>exampleSharedVector is a main program that has the code for the
|
||||
examples shown below.</p>
|
||||
<h3>Member Types</h3>
|
||||
<p>Brief Summary
|
||||
<pre>
|
||||
value_type Type of element
|
||||
size_type Unsigned type of subscripts, element counts, etc.
|
||||
difference_type Signed type of difference between iterators
|
||||
iterator Behaves like value_type*
|
||||
const_iterator Behaves like const value_type*
|
||||
reverse_iterator Behaves like value_type*
|
||||
const_reverse_iterator Behaves like const value_type*
|
||||
reference value_types&
|
||||
const_reference const_value_type&
|
||||
pointer Behaves like value_type *
|
||||
const_pointer Behaves like const value_type*
|
||||
//not part of std::vector
|
||||
element_type same as value_type
|
||||
shared_pointer_type std::tr1::shared_ptr<value_type>
|
||||
// defined by std::vector but not by shared_vector
|
||||
allocator_type
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
The typedefs are compatible with the STL container member types.
|
||||
These define types for various types of variables that belong to a container
|
||||
or are used to access a container.</p>
|
||||
<h4>value_type, reference, and const_reference</h4>
|
||||
<p>These three typedefs define the same types as the equivalent types for
|
||||
an element of the shared_vector.
|
||||
<pre>
|
||||
Int32Array::value_type value;
|
||||
//is the same as
|
||||
int32 value;
|
||||
|
||||
Int32Array::reference rvalue = value;
|
||||
//is the same as
|
||||
int32 & rvalue = value;
|
||||
|
||||
Int32Array::const_reference rvalue = value;
|
||||
//is the same as
|
||||
const int32 & rvalue = value;
|
||||
</pre>
|
||||
</p>
|
||||
<h4>pointer and const_pointer</h4>
|
||||
<p>The following is an example of code that uses the
|
||||
pointer typedef:</p>
|
||||
<pre>
|
||||
Int32Array int32Array(5);
|
||||
Int32Array::pointer pint32Array = int32Array.data();
|
||||
size_t len = int32Array.size();
|
||||
for(size_t i=0; i<len; ++i) pint32Array[i] = i;
|
||||
</pre>
|
||||
<p>A const_pointer is like a pointer except that only read access to the array elements
|
||||
is allowed.</p>
|
||||
<p><b>Dangorous: data</b> should not be used unless it is necessary to
|
||||
call C code. The above code should be:</p>
|
||||
<pre>
|
||||
Int32Array int32Array(5);
|
||||
size_t len = int32Array.size();
|
||||
for(size_t i=0; i<len; ++i) int32Array[i] = i;
|
||||
</pre>
|
||||
|
||||
<h4>difference_type</h4>
|
||||
<p>This is used to get the number of elements between two elements.
|
||||
For example:</p>
|
||||
<pre>
|
||||
Int32Array::difference_type pdiff = int32Array[3] - int32Array[1];
|
||||
// pdiff will have the value 2
|
||||
</pre>
|
||||
<h4>element_type and shared_pointer_type</h4>
|
||||
<p>These are member types defined by std::tr1::shared_ptr.
|
||||
These are not used by any of the client methods.</p>
|
||||
|
||||
<h3>Constructors, Destructor, and Assignments</h3>
|
||||
<p>Brief Summary
|
||||
<pre>
|
||||
C c(); Default constructor; c is empty.
|
||||
C c(n); c is initialized with n elementis with the value value_type{};
|
||||
offset is 0; size is n;
|
||||
C c(n,e); Initialize c with n copies of e.
|
||||
offset is 0; size is n;
|
||||
|
||||
C c(c); Copy an existing shared_vector of the same type.
|
||||
offset and taken same as v.
|
||||
shared_ptr is copied; not the raw array
|
||||
C operator=(c) Assignment constructor.
|
||||
shared_ptr is copied; not the raw array
|
||||
C c(c,o,n); Copy an existing std::tr1::shared_ptr<value_type>
|
||||
offset is o; size is c;
|
||||
C c(r,o,n); Use an existing raw pointer.
|
||||
default deleter use "delete[]" to delete.
|
||||
offset is o; size is c;
|
||||
C c(r,d,o,n); Use an existing raw pointer and deleter d;
|
||||
offset is o; size is c;
|
||||
|
||||
not implemented
|
||||
~C() The C++ default destructor is used.
|
||||
C++11 specific
|
||||
&& constructor move constructor
|
||||
{} constructor uniform initializer constructor
|
||||
</pre>
|
||||
where
|
||||
<dl>
|
||||
<dt>C</dt>
|
||||
<dd>The class name, e. g. shared_vector<int32></dd>
|
||||
<dt>c</dt>
|
||||
<dd>shared_vector instance</dd>
|
||||
<dt>n</dt>
|
||||
<dd>size, i. e. the number of elements</dd>
|
||||
<dt>o</dt>
|
||||
<dd>offset</dd>
|
||||
<dt>e</dt>
|
||||
<dd>element instance</dd>
|
||||
<dt>r</dt>
|
||||
<dd>raw pointer, e. g. int32 *</dd>
|
||||
<dt>d</dt>
|
||||
<dd>a deleter, i. e. object that destroys the raw array.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<h4>Construct by creating new raw array</h4>
|
||||
<pre>
|
||||
shared_vector();
|
||||
shared_vector(size_t n);
|
||||
shared_vector(size_t n, value_type e);
|
||||
</pre>
|
||||
<p>The first three constructors all create a new shared_vector
|
||||
by also creating a new raw array,
|
||||
The difference is the size of the array, i.e. how many elements it contains,
|
||||
and how the elements are initalized.
|
||||
</p>
|
||||
<dl>
|
||||
<dt>shared_vector()</dt>
|
||||
<dd>The array is empty, i.e. it has no elements.</dd>
|
||||
<dt>shared_vector(size_t n)</dt>
|
||||
<dd>The array has <b>n</b> elements. Each element is initialized
|
||||
by the default constructor for the element type.
|
||||
For numeric elements, like int32, this means 0.</dd>
|
||||
<dt>shared_vector(size_t n, value_type e)</dt>
|
||||
<dd>The array has <b>n</b> elements.
|
||||
Each element has the initial value <b>e</b>.
|
||||
</dd>
|
||||
</dl>
|
||||
<p>The following:
|
||||
<pre>
|
||||
cout << "***exampleConstructors***" << endl;
|
||||
Int32Array emptyArray();
|
||||
Int32Array zeroArray(16);
|
||||
int32 value = 1;
|
||||
Int32Array oneArray(8, value);
|
||||
dumpArray("emptyArray",emptyArray);
|
||||
dumpArray("zeroArray",zeroArray);
|
||||
dumpArray("oneArray",oneArray);
|
||||
</pre>
|
||||
produces
|
||||
<pre>
|
||||
***exampleConstructors***
|
||||
emptyArray 1
|
||||
zeroArray {16}[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...]
|
||||
oneArray {8}[1, 1, 1, 1, 1, 1, 1, 1]
|
||||
</pre>
|
||||
<p><b>NOTE EXISTING: </b> Why did emptyArray disply the above.
|
||||
Should it be "emptyArray {0} []"?
|
||||
</p>
|
||||
<h4>Construct by sharing raw array from a shared_vector</h4>
|
||||
<pre>
|
||||
shared_vector(const shared_vector& o);
|
||||
shared_vector_base& operator=(const shared_vector_base& o);
|
||||
</pre>
|
||||
<p>These create a vector by coping the contents of an existing shared_vector
|
||||
of the same type into the newly created vector.
|
||||
Note that the complete raw array is not copied but just the std::tr1:: shared_ptr
|
||||
that holds the array.</p>
|
||||
<p>The following:
|
||||
<pre>
|
||||
cout << "***exampleCopyConstructors***" << endl;
|
||||
size_t max = 16;
|
||||
Int32Array int32Array(max);
|
||||
for(size_t i=0; i<max; ++i) int32Array[i] = i+1;
|
||||
Int32Array xxx(int32Array); //copy constructor
|
||||
Int32Array yyy = int32Array; //copy assignment
|
||||
cout << "dataPtr int32Array " << int32Array.dataPtr();
|
||||
cout << " xxx " << xxx.dataPtr();
|
||||
cout << " yyy " << yyy.dataPtr() << endl;
|
||||
dumpArray("int32Array",emptyArray);
|
||||
dumpArray("xxx",emptyArray);
|
||||
dumpArray("yyy",emptyArray);
|
||||
</pre>
|
||||
produces
|
||||
<pre>
|
||||
***exampleConstructors***
|
||||
dataPtr int32Array 0x136ea90 xxx 0x136ea90 yyy 0x136ea90
|
||||
int32Array {16}[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]
|
||||
xxx {16}[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]
|
||||
yyy {16}[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]
|
||||
</pre>
|
||||
<h4>Construct by wrapping an existing raw array</h4>
|
||||
<pre>
|
||||
shared_vector(A v, size_t o, size_t c)
|
||||
shared_vector(A d, B b, size_t o, size_t c)
|
||||
</pre>
|
||||
<p><b>NOTE EXISTING:</b> Are these constructors necessary?
|
||||
If code wants to wrap an existing raw array then
|
||||
a std::tr1::shared_ptr can first be created
|
||||
and the constructor in the next section can be called.</p>
|
||||
<p>These "wrap" an existing raw pointer.
|
||||
They allows access to a sub-array starting at offset <b>o></b>
|
||||
and has size <b>c</b>
|
||||
The second provides a destructor and the first has a default deleter.</p>
|
||||
<p>The default deleter does the following:
|
||||
When the shared_vector is deleted, i. e. when no code references it,
|
||||
the statement "delete[] a;" is executed.</p>
|
||||
<p>An example of wrapping a raw array without using these constructors is:</p>
|
||||
<pre>
|
||||
class Int32ArrayDeleter
|
||||
{
|
||||
//Note that this an example that does nothing.
|
||||
//But it could have private data
|
||||
public:
|
||||
Int32ArrayDeleter() {}
|
||||
virtual ~Int32ArrayDeleter() {}
|
||||
void operator()(int32* a){
|
||||
// MUST HANDLE DELETION
|
||||
// default is "delete[] a;"
|
||||
}
|
||||
};
|
||||
...
|
||||
int32 *pother; // something managed by other code
|
||||
size_t capacity; // size of array managed by other code
|
||||
|
||||
Int32Array int32Array(pother,int32array_deleter,0,capacity);
|
||||
</pre>
|
||||
<p>This is used to wrap arrays that are managed by other
|
||||
code. This should only be used if You understand the other code
|
||||
and know what your deleter has to do.
|
||||
An example, exampleShareRawArray, gives a more complete example.
|
||||
</p>
|
||||
|
||||
<h4>Create a shared_vector from an existing shared_ptr</h4>
|
||||
<pre>
|
||||
shared_vector(const std::tr1::shared_ptr<E1>& d, size_t o, size_t c)
|
||||
</pre>
|
||||
<p>This creates a vector from an existing smart pointer.
|
||||
Thus the vector will share reference counting with the existing smart
|
||||
pointer. This is useful for creating "windows" into the array
|
||||
that the smart pointer references.</p>
|
||||
|
||||
|
||||
|
||||
<h4>Create a shared_vector from an existing shared_vector</h4>
|
||||
<pre>
|
||||
template<typename E1>
|
||||
shared_vector(const shared_vector<E1>& o) :base_t(o) {}
|
||||
</pre>
|
||||
<p><b>NOTE EXISTING:</b> I do not understand how this works or what it does.</p>
|
||||
<p>This create a vector by coping the contents of an existing shared_vector
|
||||
of the same or a different but related type
|
||||
into the newly created vector.
|
||||
This constructor creates a new raw array and copies the elements from
|
||||
the existing array to the new array.</p>
|
||||
|
||||
<h3>Size and Capacity</h3>
|
||||
<p>Brief Summary
|
||||
<pre>
|
||||
size() Return the number of elements in the window
|
||||
empty() Is the window empty? this means shared_ptr is empty
|
||||
max_size() The maximum possible number of elements.
|
||||
capacity() The number of possible elements without re-allocating raw array.
|
||||
reserve(n) Reserve at least n elements in raw array; May cause reallocation.
|
||||
resize(n) Change size to n; May cause reallocation
|
||||
clear() shared_ptr is reset, Window will be empty.
|
||||
|
||||
not implemented
|
||||
resize(n,v)
|
||||
shrink_to_fit()
|
||||
</pre></p>
|
||||
<p>Details
|
||||
<pre>
|
||||
size_t size() const;
|
||||
bool empty() const;
|
||||
size_t max_size() const;
|
||||
size_t capacity() const;
|
||||
void reserve(size_t n);
|
||||
void resize(size_t n);
|
||||
void clear();
|
||||
</pre>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>size</dt>
|
||||
<dd>The current number of elements in the window.</dd>
|
||||
<dt>empty</dt>
|
||||
<dd>(true,false) if size is (0,>0)</dd>
|
||||
<dt>max_size</dt>
|
||||
<dd>Maximum possible number of elements.
|
||||
<b>NOTE EXISTING;</b> Should this be sizof(W)/(size_t -1) ?
|
||||
</dd>
|
||||
<dt>capacity</dt>
|
||||
<dd>The maximum size the window can be without reallocating raw array</dd>
|
||||
<dt>reserve</dt>
|
||||
<dd>Set the maximum number of element that the window can see.
|
||||
If the caller is the only user of the window and the number
|
||||
of elements specified does not cause the number of elements to change
|
||||
then this method just returns.
|
||||
In all other cases a new raw array is allocated.</p>
|
||||
<dt>resize</dt>
|
||||
<dd>Change the window size: may cause a reallocation of the raw array.</dd>
|
||||
<dt>clear</dt>
|
||||
<dd>If the shared_vector is not already empty the shared_ptr will
|
||||
be reset. The new size will be 0.</dd>
|
||||
</dl>
|
||||
<p>The following:
|
||||
<pre>
|
||||
static void exampleSizeEtc()
|
||||
{
|
||||
cout << "***exampleSizeEtc***" << endl;
|
||||
size_t max = 16;
|
||||
Int32Array int32Array(max);
|
||||
size_t capacity = int32Array.capacity();
|
||||
size_t size = int32Array.size();
|
||||
bool empty = int32Array.empty();
|
||||
size_t max_size = int32Array.max_size();
|
||||
cout<< "capacity" << capacity;
|
||||
cout<< " size " << size;
|
||||
cout<< " empty " << (empty ? true : false) ;
|
||||
cout<< " max_size " << max_size << endl;
|
||||
}
|
||||
|
||||
</pre>
|
||||
produces:
|
||||
<pre>
|
||||
***exampleSizeEtc***
|
||||
capacity16 size 16 empty 0 max_size 18446744073709551615
|
||||
</pre>
|
||||
</p>
|
||||
<h3>Iterators</h3>
|
||||
<p>Brief Summary
|
||||
<pre>
|
||||
begin() First element
|
||||
end() One past last element
|
||||
cbegin() Constant first element
|
||||
cend() Constant last element
|
||||
rbegin() First element of reverse sequence
|
||||
rend() One past last element of reverse sequence
|
||||
crbegin() Constant first element of reverse sequence
|
||||
crend() Constant last element of reverse sequence
|
||||
</pre></p>
|
||||
<p>
|
||||
shared_vector supports both iterators and reverse iterators as defined by the STL.
|
||||
For both constant iterators are also defined.
|
||||
A constant iterator does not allow an array elemnent to be modified.</p>
|
||||
<p>The following is an example of a constant iterator.</p>
|
||||
<pre>
|
||||
int32 sum = 0;
|
||||
for(Int32Array::const_iterator iter=int32Array.begin(); iter<int32Array.end(); ++iter )
|
||||
{
|
||||
sum += *iter;
|
||||
}
|
||||
</pre>
|
||||
<p>The following is an example of a non constant iterator.</p>
|
||||
<pre>
|
||||
int32 value = 0;
|
||||
for(Int32Array::iterator iter=int32Array.begin(); iter<int32Array.end(); ++iter )
|
||||
{
|
||||
*iter += ++value;
|
||||
}
|
||||
</pre>
|
||||
<h3>Element Access</h3>
|
||||
<p>Brief Summary
|
||||
<pre>
|
||||
operator[i] random element access
|
||||
data() return the raw array
|
||||
|
||||
implemented by std::vector but not implemented
|
||||
front()
|
||||
back()
|
||||
at()
|
||||
</pre></p>
|
||||
<p>Note that:
|
||||
<pre>
|
||||
Int32Array::pointer pint32= int32Array.data();
|
||||
</pre>
|
||||
<b>is NOT gauranteed to be the same as</b>
|
||||
<pre>
|
||||
int32 * pint32 = int32Array.data();
|
||||
</pre>
|
||||
</p>
|
||||
<p><b>NOTE EXISTING: data()</b> should be defined to return a const_pointer.
|
||||
It is currently defined to return a plain pointer.</p>
|
||||
<h3>Stack Operations</h3>
|
||||
<p>Brief Summary
|
||||
<pre>
|
||||
push_back(x) Add an element after the last element
|
||||
pop_back(x) Remove the last element.
|
||||
</pre></p>
|
||||
<h3>List operations</h3>
|
||||
<p>shared_vector does not support the standard list operations like:
|
||||
<pre>
|
||||
implemented by std::vector but not by shared_vector
|
||||
|
||||
insert(p,x) Add x before p
|
||||
...
|
||||
</pre>
|
||||
</p>
|
||||
<h3>Other Operations</h3>
|
||||
<p>Brief Summary
|
||||
<pre>
|
||||
operator== Do all elements of both containers compare equal.
|
||||
operator!= Does any element not compare equal.
|
||||
operator<< ostream operator
|
||||
swap(c2) Swap the contents of two shared_vectors of the same type.
|
||||
swap(c1,c2) Swap the contents of two shared_vectors of the same type.
|
||||
|
||||
not implemented
|
||||
operator<
|
||||
operator<=
|
||||
operator>
|
||||
operator>=
|
||||
</pre></p>
|
||||
<h4>operators equals, not equals, and ostream</h4>
|
||||
<pre>
|
||||
template<typename A, typename B>
|
||||
bool operator==(const epics::pvData::shared_vector<A>& a,
|
||||
const epics::pvData::shared_vector<B>& b);
|
||||
|
||||
template<typename A, typename B>
|
||||
bool operator!=(const epics::pvData::shared_vector<A>& a,
|
||||
const epics::pvData::shared_vector<B>& b);
|
||||
|
||||
template<typename E>
|
||||
std::ostream& operator<<(
|
||||
std::ostream& strm, const epics::pvData::shared_vector<E>& arr);
|
||||
|
||||
</pre>
|
||||
<h4>swap</h4>
|
||||
<p>Swap the contents of two shared_vectors. The following code:
|
||||
<pre>
|
||||
cout << "***exampleSwap***" << endl;
|
||||
Int32Array first(8);
|
||||
Int32Array second(16);
|
||||
cout << " before swap size ";
|
||||
cout<< "first " << first.size() << " second " << second.size() << endl;
|
||||
first.swap(second);
|
||||
cout << " after swap size ";
|
||||
cout<< "first " << first.size() << " second " << second.size() << endl;
|
||||
swap(first,second);
|
||||
cout << " swap again size ";
|
||||
cout<< "first " << first.size() << " second " << second.size() << endl;
|
||||
</pre>
|
||||
produces:
|
||||
<pre>
|
||||
***exampleSwap***
|
||||
before swap size first 8 second 16
|
||||
after swap size first 16 second 8
|
||||
swap again size first 8 second 16
|
||||
</pre></p>
|
||||
|
||||
<h3>shared_vector specific operations</h3>
|
||||
<p>Brief Summary
|
||||
<pre>
|
||||
void make_unique() Make caller the only user of std::tr1::shared_ptr
|
||||
bool unique() Is the caller the only user of std::tr1::shared_ptr
|
||||
void slice(offset,length) Change window offset andsize
|
||||
|
||||
// following should only be used for debugging
|
||||
const std::tr1::shared_ptr<E>&
|
||||
dataPtr() Return const shared_ptr
|
||||
size_t dataOffset() Return offset.
|
||||
size_t dataCount() Return count which is also the size
|
||||
size_t dataTotal() Return total number of elements between
|
||||
offset and end of the raw array
|
||||
|
||||
// following converts from type FROM to type TO
|
||||
shared_vector<TO> static_shared_vector_cast(const shared_vector<FROM>& src);
|
||||
|
||||
// following casts from const Type to Type
|
||||
shared_vector<TYPE>
|
||||
const_shared_vector_cast(const shared_vector<const TYPE>& src)
|
||||
</pre></p>
|
||||
<p><b>NOTE EXISTING:</b> The C++ standard library considers a slice to be every nth element
|
||||
of some part of an array, i. e., slice has arguments (offset,length,stride).
|
||||
shared_vector only has offset and length.
|
||||
Perhaps it should have another name like rewindow.
|
||||
<h4>make_unique and unique</h4>
|
||||
<pre>
|
||||
void make_unique();
|
||||
bool unique() const;
|
||||
</pre>
|
||||
<dl>
|
||||
<dt>make_unique</dt>
|
||||
<dd>Makes sure that caller is the only user of this standard_vector.
|
||||
If the caller is not already the only user a new raw array is allocated.</dd>
|
||||
<dt>unique</dt>
|
||||
<dd>
|
||||
Returns (true,false) if there is only one user of the shared_vector.
|
||||
</dd>
|
||||
</dl>
|
||||
<h4>slice</h4>
|
||||
<pre>
|
||||
void slice(size_t offset, size_t length=(size_t)-1);
|
||||
</pre>
|
||||
<p>This modifies the "window" into the raw array starting at offset and of
|
||||
the specified length. The offset and length are forced to be
|
||||
within the raw array.
|
||||
Note that this method never reallocates the underlying raw array.
|
||||
</p>
|
||||
<p>The following code:
|
||||
<pre>
|
||||
static void exampleSlice()
|
||||
{
|
||||
cout << "***exampleSlice***" << endl;
|
||||
size_t max = 16;
|
||||
Int32Array int32Array(max);
|
||||
int32 value = 0;
|
||||
for(Int32Array::iterator iter = int32Array.begin(); iter!=int32Array.end(); ++iter)
|
||||
{
|
||||
*iter = ++value;
|
||||
}
|
||||
dumpArray("int32Array",int32Array);
|
||||
size_t offset = 0;
|
||||
size_t length = 8;
|
||||
Int32Array window1(int32Array);
|
||||
window1.slice(offset,length);
|
||||
dumpArray("window1",window1);
|
||||
offset = 8;
|
||||
length = 8;
|
||||
Int32Array window2(int32Array);
|
||||
window2.slice(offset,length);
|
||||
dumpArray("window2",window2);
|
||||
offset = 2;
|
||||
length = 4;
|
||||
Int32Array window3(window2);
|
||||
window3.slice(offset,length);
|
||||
dumpArray("window3",window3);
|
||||
}
|
||||
</pre>
|
||||
produces the following output:
|
||||
<pre>
|
||||
***exampleSlice***
|
||||
int32Array 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
||||
window1 1 2 3 4 5 6 7 8
|
||||
window2 9 10 11 12 13 14 15 16
|
||||
window3 11 12 13 14
|
||||
</pre>
|
||||
<h4>dataPtr, dataOffset, dataCount, and dataTotal</h4>
|
||||
<dl>
|
||||
<dt>dataPtr</dt>
|
||||
<dd>Returns the shared_ptr that holds the raw array.
|
||||
</dd>
|
||||
<dt>dataOffset</dt>
|
||||
<dd>Offset in the data array of first element</dd>
|
||||
<dt>dataCount</dt>
|
||||
<dd>Number of visible elements.
|
||||
Same as size.
|
||||
</dd>
|
||||
<dt>dataTotal</dt>
|
||||
<dd>Total number of elements between m_offset and the end of data.
|
||||
Same as capacity.
|
||||
</dd>
|
||||
</dl>
|
||||
<p>The following:
|
||||
<pre>
|
||||
static void exampleDataEtc()
|
||||
{
|
||||
cout << "***exampleDataEtc***" << endl;
|
||||
size_t max = 16;
|
||||
Int32Array int32Array(max);
|
||||
long use_count = int32Array.dataPtr().use_count();
|
||||
long offset = int32Array.dataOffset();
|
||||
long count = int32Array.dataCount();
|
||||
long total = int32Array.dataTotal();
|
||||
cout << "use_count " << use_count;
|
||||
cout << " offset " << offset;
|
||||
cout << " count " << count;
|
||||
cout << " total " << total << endl;
|
||||
}
|
||||
</pre>
|
||||
produces:
|
||||
<pre>
|
||||
***exampleDataEtc***
|
||||
use_count 1 offset 0 count 16 total 16
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h4>static_shared_vector_cast</h4>
|
||||
<p>Not yet documented</p>
|
||||
|
||||
<h4>const_shared_vector_cast</h4>
|
||||
<p>Not yet documented</p>
|
||||
|
||||
<h4>specialization for untyped pointers</h4>
|
||||
<p>Not yet documented</p>
|
||||
|
||||
<h2>pvDataApp/pv</h2>
|
||||
<p><b>INGORE REST OF DOCUMENT!!!!</b></p>
|
||||
<h3>pvData.h</h3>
|
||||
|
||||
<h4>PVArray</h4>
|
||||
|
||||
<p>PVArray is the base interface for all the other PV Array interfaces. It
|
||||
extends PVField and provides the additional methods:</p>
|
||||
<pre>class PVArray : public PVField, public SerializableArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVArray);
|
||||
virtual ~PVArray();
|
||||
virtual void setImmutable();
|
||||
std::size_t getLength() const;
|
||||
virtual void setLength(std::size_t length);
|
||||
std::size_t getCapacity() const;
|
||||
bool isCapacityMutable() const;
|
||||
void setCapacityMutable(bool isMutable);
|
||||
virtual void setCapacity(std::size_t capacity) = 0;
|
||||
...
|
||||
};</pre>
|
||||
<dl>
|
||||
<dt>setImmutable</dt>
|
||||
<dd>Set the data immutable. Note that this is permanent since there is no
|
||||
methods to make it mutable.</dd>
|
||||
<dt>getLength</dt>
|
||||
<dd>Get the current length. This is less than or equal to the capacity.</dd>
|
||||
<dt>setLength</dt>
|
||||
<dd>Set the length. If the PVField is not mutable then an exception is
|
||||
thrown. If this is greater than the capacity setCapacity is called.</dd>
|
||||
<dt>getCapacity</dt>
|
||||
<dd>Get the capacity, i.e. this is the size of the underlying data
|
||||
array.</dd>
|
||||
<dt>setCapacity</dt>
|
||||
<dd>Set the capacity. The semantics are implementation dependent but
|
||||
typical semantics are as follows: If the capacity is not mutable an
|
||||
exception is thrown. A new data array is created and data is copied from
|
||||
the old array to the new array. </dd>
|
||||
<dt>isCapacityMutable</dt>
|
||||
<dd>Is the capacity mutable</dd>
|
||||
<dt>setCapacityMutable</dt>
|
||||
<dd>Specify if the capacity can be changed.</dd>
|
||||
<dt>setCapacity</dt>
|
||||
<dd>Set the capaciity.</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
<h4>PVScalarArray</h4>
|
||||
|
||||
<p>PVScalarArray is the base class for scalar array data. PVValueArray is a
|
||||
templete for the various scalar array data classes. There is a class for each
|
||||
possible scalar type, i. e. PVBooleanArray, ..., PVStringArray.</p>
|
||||
<pre>class PVScalarArray : public PVArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVScalarArray);
|
||||
virtual ~PVScalarArray();
|
||||
typedef PVScalarArray &reference;
|
||||
typedef const PVScalarArray& const_reference;
|
||||
const ScalarArrayConstPtr getScalarArray() const ;
|
||||
virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
|
||||
...
|
||||
}</pre>
|
||||
|
||||
<p>where</p>
|
||||
<dl>
|
||||
<dt>getScalarArray</dt>
|
||||
<dd>Get the introspection interface.</dd>
|
||||
<dt>dumpValue</dt>
|
||||
<dd>Method for streams I/O.</dd>
|
||||
</dl>
|
||||
|
||||
<h4>PVValueArray</h4>
|
||||
|
||||
<p>This is a template class plus instances for PVBooleanArray, ...,
|
||||
PVStringArray.</p>
|
||||
<pre>template<typename T>
|
||||
class PVValueArray : public PVScalarArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVValueArray);
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef PVArrayData<T> ArrayDataType;
|
||||
typedef std::vector<T> vector;
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVValueArray & reference;
|
||||
typedef const PVValueArray & const_reference;
|
||||
|
||||
virtual ~PVValueArray() {}
|
||||
virtual std::size_t get(
|
||||
std::size_t offset, std::size_t length, ArrayDataType &data) = 0;
|
||||
virtual std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_pointer from, std::size_t fromOffset) = 0;
|
||||
virtual std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_vector &from, std::size_t fromOffset);
|
||||
virtual void shareData(
|
||||
shared_vector const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length) = 0;
|
||||
virtual pointer get() = 0;
|
||||
virtual pointer get() const = 0;
|
||||
virtual vector const & getVector() = 0;
|
||||
virtual shared_vector const & getSharedVector() = 0;
|
||||
std::ostream& dumpValue(std::ostream& o) const;
|
||||
std::ostream& dumpValue(std::ostream& o, size_t index) const;
|
||||
protected:
|
||||
PVValueArray(ScalarArrayConstPtr const & scalar)
|
||||
: PVScalarArray(scalar) {}
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::size_t PVValueArray<T>::put(
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
const_vector &from,
|
||||
std::size_t fromOffset)
|
||||
{ return put(offset,length, &from[0], fromOffset); }
|
||||
|
||||
/**
|
||||
* Definitions for the various scalarArray types.
|
||||
*/
|
||||
typedef PVArrayData<uint8> BooleanArrayData;
|
||||
typedef PVValueArray<uint8> PVBooleanArray;
|
||||
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
|
||||
|
||||
typedef PVArrayData<int8> ByteArrayData;
|
||||
typedef PVValueArray<int8> PVByteArray;
|
||||
typedef std::tr1::shared_ptr<PVByteArray> PVByteArrayPtr;
|
||||
|
||||
typedef PVArrayData<int16> ShortArrayData;
|
||||
typedef PVValueArray<int16> PVShortArray;
|
||||
typedef std::tr1::shared_ptr<PVShortArray> PVShortArrayPtr;
|
||||
|
||||
typedef PVArrayData<int32> IntArrayData;
|
||||
typedef PVValueArray<int32> PVIntArray;
|
||||
typedef std::tr1::shared_ptr<PVIntArray> PVIntArrayPtr;
|
||||
|
||||
typedef PVArrayData<int64> LongArrayData;
|
||||
typedef PVValueArray<int64> PVLongArray;
|
||||
typedef std::tr1::shared_ptr<PVLongArray> PVLongArrayPtr;
|
||||
|
||||
typedef PVArrayData<uint8> UByteArrayData;
|
||||
typedef PVValueArray<uint8> PVUByteArray;
|
||||
typedef std::tr1::shared_ptr<PVUByteArray> PVUByteArrayPtr;
|
||||
|
||||
typedef PVArrayData<uint16> UShortArrayData;
|
||||
typedef PVValueArray<uint16> PVUShortArray;
|
||||
typedef std::tr1::shared_ptr<PVUShortArray> PVUShortArrayPtr;
|
||||
|
||||
typedef PVArrayData<uint32> UIntArrayData;
|
||||
typedef PVValueArray<uint32> PVUIntArray;
|
||||
typedef std::tr1::shared_ptr<PVUIntArray> PVUIntArrayPtr;
|
||||
|
||||
typedef PVArrayData<uint64> ULongArrayData;
|
||||
typedef PVValueArray<uint64> PVULongArray;
|
||||
typedef std::tr1::shared_ptr<PVULongArray> PVULongArrayPtr;
|
||||
|
||||
typedef PVArrayData<float> FloatArrayData;
|
||||
typedef PVValueArray<float> PVFloatArray;
|
||||
typedef std::tr1::shared_ptr<PVFloatArray> PVFloatArrayPtr;
|
||||
|
||||
typedef PVArrayData<double> DoubleArrayData;
|
||||
typedef PVValueArray<double> PVDoubleArray;
|
||||
typedef std::tr1::shared_ptr<PVDoubleArray> PVDoubleArrayPtr;
|
||||
|
||||
typedef PVArrayData<String> StringArrayData;
|
||||
typedef PVValueArray<String> PVStringArray;
|
||||
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;</pre>
|
||||
|
||||
<p>where</p>
|
||||
<dl>
|
||||
<dt>get( std::size_t offset, std::size_t length, ArrayDataType &data)
|
||||
</dt>
|
||||
<dd>This method "exposes" it's internal array by setting data.data and
|
||||
data.offset. The caller is responsible for copying the array elements.
|
||||
This violates the principle that objects should not expose their internal
|
||||
data but is done for efficency. For example it makes it possible to copy
|
||||
between arrays with identical element types without requiring an
|
||||
intermediate array.</dd>
|
||||
<dt>put(std::size_t offset, std::size_t length, const_pointer from,
|
||||
std::size_t fromOffset)</dt>
|
||||
<dd>Put data into the array. from is a raw array.</dd>
|
||||
<dt>put(std::size_t offset, std::size_t length, const_vector &from,
|
||||
std::size_t fromOffset)</dt>
|
||||
<dd>Put data into the array from a vector holding the raw array.</dd>
|
||||
<dt>shareData( shared_vector const & value, std::size_t capacity,
|
||||
std::size_t length)</dt>
|
||||
<dd>Make the instance share the raw data from value.<br />
|
||||
One use is
|
||||
for immutable arrays. In this case the caller must set the PVArray to be
|
||||
immutable. In the PVArray is not immutable then it is the applications
|
||||
responsibility to coordinate access to the array. Again this violates the
|
||||
principle that objects should not expose their internal data but is
|
||||
important for immutable arrays. For example pvData and the javaIOC define
|
||||
many enumerated structures where an enumerated structure has two fields:
|
||||
index and choices. Choices is a PVStringArray that holds the enumerated
|
||||
choices. Index is a PVInt that is the index of the currently selected
|
||||
choice. For many enumerated structures choices is immutable. Allowing the
|
||||
choices internal String[] to be shared between all the instances of an
|
||||
enumerated structure saves on storage.<br />
|
||||
Another use for shared data is an application which processes an
|
||||
array via multiple modules. Each accesses the internal data array of a
|
||||
PVArray. In this case it is the applications responsibility
|
||||
to coordinate access to the array.</dd>
|
||||
<dt>get()</dt>
|
||||
<dd>Get the raw array.</dd>
|
||||
<dt>getVector()</dt>
|
||||
<dd>Get the vector holding the raw array.</dd>
|
||||
<dt>getSharedVector()</dt>
|
||||
<dd>Get the shared vector holding the data.</dd>
|
||||
<dt>dumpValue</dt>
|
||||
<dd>Method for streams I/O.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Both get and put return the number of elements actually transfered. The
|
||||
arguments are:</p>
|
||||
<dl>
|
||||
<dt>offset</dt>
|
||||
<dd>The offset in the PV array.</dd>
|
||||
<dt>len</dt>
|
||||
<dd>The maximum number of elements to transfer. The number actually
|
||||
transfered will be less than or equal to this value.</dd>
|
||||
<dt>data</dt>
|
||||
<dd>Get sets data.data to it's internal array and data.offset to the offset
|
||||
into the array. The caller is responsible for the actual data
|
||||
transfer.</dd>
|
||||
<dt>from</dt>
|
||||
<dd>The array from which the data is taken. This array is supplied by the
|
||||
caller</dd>
|
||||
<dt>fromOffset</dt>
|
||||
<dd>The offset in from</dd>
|
||||
</dl>
|
||||
|
||||
<p>The caller must be prepared to make multiple calls to retrieve or put an
|
||||
entire array. A caller should accept or put partial arrays. For example the
|
||||
following reads an entire array:</p>
|
||||
<pre>void getArray(PVDoubleArrayPtr & pv,DoubleArray const & to)
|
||||
{
|
||||
size_t len = pv->getLength();
|
||||
if(to.size()<len) to.resize(len);
|
||||
DoubleArrayData data;
|
||||
size_t offset = 0;
|
||||
while(offset<len) {
|
||||
size_t num = pv->get(offset,(len-offset),data);
|
||||
DoubleArray &from = data.data;
|
||||
size_t fromOffset = data.offset;
|
||||
for(size_t i=0; i<num; i++) to[i+offset] = from[i + fromOffset];
|
||||
offset += num;
|
||||
}
|
||||
} </pre>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -29,9 +29,9 @@ public:
|
||||
int getNumberFree();
|
||||
int getNumberUsed();
|
||||
queueElementPtr & getFree();
|
||||
void setUsed(queueElementPtr &element);
|
||||
void setUsed(queueElementPtr const &element);
|
||||
queueElementPtr & getUsed();
|
||||
void releaseUsed(queueElementPtr &element);
|
||||
void releaseUsed(queueElementPtr const &element);
|
||||
private:
|
||||
queueElementPtr nullElement;
|
||||
queueElementPtrArray elements;
|
||||
@@ -92,7 +92,7 @@ std::tr1::shared_ptr<T> & Queue<T>::getFree()
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Queue<T>::setUsed(std::tr1::shared_ptr<T> &element)
|
||||
void Queue<T>::setUsed(std::tr1::shared_ptr<T> const &element)
|
||||
{
|
||||
if(element!=elements[nextSetUsed++]) {
|
||||
throw std::logic_error("not correct queueElement");
|
||||
@@ -112,7 +112,7 @@ std::tr1::shared_ptr<T> & Queue<T>::getUsed()
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Queue<T>::releaseUsed(std::tr1::shared_ptr<T> &element)
|
||||
void Queue<T>::releaseUsed(std::tr1::shared_ptr<T> const &element)
|
||||
{
|
||||
if(element!=elements[nextReleaseUsed++]) {
|
||||
throw std::logic_error(
|
||||
|
||||
@@ -13,25 +13,31 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
static bool checkBitSetPVField(
|
||||
PVField *pvField,BitSet *bitSet,int32 initialOffset)
|
||||
PVFieldPtr const &pvField,BitSetPtr const &bitSet,int32 initialOffset)
|
||||
{
|
||||
bool atLeastOneBitSet = false;
|
||||
bool allBitsSet = true;
|
||||
int32 offset = initialOffset;
|
||||
int32 nbits = pvField->getNumberFields();
|
||||
if(nbits==1) return bitSet->get(offset);
|
||||
int32 nextSetBit = bitSet->nextSetBit(offset);
|
||||
if(nextSetBit>=(offset+nbits)) return false;
|
||||
if(nextSetBit<0) return false;
|
||||
if(bitSet->get(offset)) {
|
||||
if(nbits>1) {
|
||||
for(int32 i=offset+1; i<offset+nbits; i++) bitSet->clear(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
PVStructure *pvStructure = static_cast<PVStructure *>(pvField);
|
||||
|
||||
bool atLeastOneBitSet = false;
|
||||
bool allBitsSet = true;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
offset = pvStructure->getFieldOffset() + 1;
|
||||
while(offset<initialOffset + nbits) {
|
||||
PVField *pvSubField = pvStructure->getSubField(offset).get();
|
||||
PVFieldPtr pvSubField = pvStructure->getSubField(offset);
|
||||
int32 nbitsNow = pvSubField->getNumberFields();
|
||||
if(nbitsNow==1) {
|
||||
if(bitSet->get(offset)) {
|
||||
@@ -41,24 +47,16 @@ static bool checkBitSetPVField(
|
||||
}
|
||||
offset++;
|
||||
} else {
|
||||
offset++;
|
||||
PVStructure *pvSubStructure = static_cast<PVStructure*>(pvField);
|
||||
PVFieldPtrArray pvSubStructureFields =
|
||||
pvSubStructure->getPVFields();
|
||||
int num = pvSubStructure->getStructure()->getNumberFields();
|
||||
for(int32 i=0; i<num; i++) {
|
||||
PVField *pvSubSubField = pvSubStructureFields[i].get();
|
||||
bool result = checkBitSetPVField(pvSubSubField,bitSet,offset);
|
||||
if(result) {
|
||||
atLeastOneBitSet = true;
|
||||
if(!bitSet->get(offset)) {
|
||||
allBitsSet = false;
|
||||
}
|
||||
} else {
|
||||
bool result = checkBitSetPVField(pvSubField,bitSet,offset);
|
||||
if(result) {
|
||||
atLeastOneBitSet = true;
|
||||
if(!bitSet->get(offset)) {
|
||||
allBitsSet = false;
|
||||
}
|
||||
offset += pvSubSubField->getNumberFields();
|
||||
} else {
|
||||
allBitsSet = false;
|
||||
}
|
||||
offset += pvSubField->getNumberFields();
|
||||
}
|
||||
}
|
||||
if(allBitsSet) {
|
||||
@@ -72,7 +70,7 @@ static bool checkBitSetPVField(
|
||||
return atLeastOneBitSet;
|
||||
}
|
||||
|
||||
bool BitSetUtil::compress(BitSet *bitSet,PVStructure *pvStructure)
|
||||
bool BitSetUtil::compress(BitSetPtr const &bitSet,PVStructurePtr const &pvStructure)
|
||||
{
|
||||
return checkBitSetPVField(pvStructure,bitSet,0);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace epics { namespace pvData {
|
||||
|
||||
class BitSetUtil : private NoDefaultMethods {
|
||||
public:
|
||||
static bool compress(BitSet *bitSet,PVStructure *pvStructure);
|
||||
static bool compress(BitSetPtr const &bitSet,PVStructurePtr const &pvStructure);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user