1843 lines
62 KiB
HTML
1843 lines
62 KiB
HTML
<?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, 28-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>Changes</h2>
|
|
<p>Since the last version of this document the following changes have
|
|
been made to the proposed interface definitionsi for PVValueArray:</p>
|
|
<dl>
|
|
<dt>put(const svector &from)</dt>
|
|
<dd>This has been removed. shareData can be used instead.</dd>
|
|
<dt>get</dt>
|
|
<dd>The get methods has been replaced by two methods.
|
|
One allows write access to array elements and the other does not.
|
|
</dd>
|
|
</dl>
|
|
<p>The stream operator++ methods were changed so that they only appear
|
|
in PVField. All the complexity should be hidden in the implementation
|
|
and, perhaps like Java, in the convert facility.</p>
|
|
<p>A few minor changes were made because of mistakes in documenting
|
|
existing API descriptions.</p>
|
|
<h2>Introduction</h2>
|
|
<p>This is the documentation for pvData.h as defined by pvDataCPP-md.
|
|
When complete it will be merged into pvDataCPP.html.
|
|
This document proposes an implementation of the PVXXX interfaces that are
|
|
different than the existing pvDataCPP-md interfaces.
|
|
See the next section for a comparison of the four interface descriptions.
|
|
The main reason for proposing a different definition is the primary
|
|
purpose for pvData:
|
|
<blockquote>pvData (Process Variable Data) defines and implements an efficent
|
|
way to store, access, and communicate memory resident data structures.</blockquote>
|
|
This statement appears as the first sentence of pvDataJava.html.
|
|
A few sentances later the document makes clear that communication
|
|
includes network communication.
|
|
Thus pvData provides an interface for network accessible structured data.
|
|
If the interfaces for C++ and Java are similar then
|
|
someone who understands the interface in one of the languages
|
|
and knows both languages will quickly understand the interface of the other language.
|
|
With only a few exceptions the naming and other conventions do
|
|
not follow the C++ standard library conventions.
|
|
The pvData.h API is similar to the definition for Java.
|
|
The differences are mainly related to language differences.
|
|
Some differences are:
|
|
<dl>
|
|
<dt>shared pointers</dt>
|
|
<dd>Java has a garbage collector. In C++ the implementation manages
|
|
memory. An important tool is std::tr1::shared_ptr.</dd>
|
|
<dt>PVArray</dt>
|
|
<dd>The Java garbage collector allows raw data arrays, e. g. int[],
|
|
to be shared. For C++ a shared_vector holds the raw data.
|
|
</dd>
|
|
<dt>ostream replaces toString</dt>
|
|
<dd>In Java every object has method toString().
|
|
For C++ stream operator<< replaces toString</dd>
|
|
<dt>shared_vector</dt>
|
|
<dd>This is similar to std::vector but uses a shared_ptr to wrap the raw
|
|
data and also supports a window into the raw data. It does follow the
|
|
naming and other conventions for C++ standard library containers.
|
|
Code that wants to use features of the C++ standard library
|
|
like iterators and algorithms can get the shared_vector.
|
|
</dd>
|
|
</dl>
|
|
<p>There is one big difference from the existing Java API:
|
|
The method PVValueArray::get.
|
|
As an example the Java definition for PVDoubleArray is currently:
|
|
<pre>
|
|
int get(int offset, int length, DoubleArrayData data);
|
|
</pre>
|
|
This document assumes this will be replaced by:
|
|
<pre>
|
|
double[] get();
|
|
</pre>
|
|
<p>The existing version allowed the data source to provide the array in chunks.
|
|
The new version assumes that the data source always provides contiguous storage
|
|
for the entire raw array. If this is accepted it simplifies a lot of code.
|
|
</p>
|
|
<p>Three topics not discussed in this document are:
|
|
<dl>
|
|
<dt>pvDataCreate</dt>
|
|
<dd>There should be a new method something like:
|
|
<pre>
|
|
PVScalarArrayPtr createPVScalarArray(const PVScalarArray &, size_t offset, size_t length);
|
|
</pre>
|
|
This will share the raw data array but allow a new window.
|
|
</dd>
|
|
<dt>convert</dt>
|
|
<dd>This will be changed to do conversions itself instead of calling
|
|
methods like getAs. It will again support methods toXXXArray and fromXXXArray.
|
|
Templates should be used to minimize the code required.</dd>
|
|
<dt>PVStructureArray</dt>
|
|
<dd>This should also be able to use shared_vector to hold elements.</dd>
|
|
</dl>
|
|
</p>
|
|
<h2>PVXXX: pvDataJava, pvDataCPP, pvDataCPP-md, and proposed interface</h2>
|
|
<p>The following compares the definitions of the following: PVField,
|
|
PVScalar and extensions, PVArray and extensions.
|
|
PVStructureArray is not discussed.
|
|
</p>
|
|
<h3>PVField</h3>
|
|
<p>This is the base for all the PVXXX iterfaces.
|
|
It provides basic methods for allowing network transfer and for
|
|
traversing structured data.
|
|
The pvDataJava and pvDataCPP definitions are similar.
|
|
pvDataCPP-md added method getFullName.
|
|
The proposed interface is like the existing pvDataCPP except that
|
|
the dumpValue method is replaced by the stream operator<<.
|
|
</p>
|
|
<h4>Java</h4>
|
|
<pre>interface PVField extends Requester, Serializable {
|
|
String getFieldName();
|
|
void setRequester(Requester requester);
|
|
int getFieldOffset();
|
|
int getNextFieldOffset();
|
|
int getNumberFields();
|
|
PVAuxInfo getPVAuxInfo();
|
|
boolean isImmutable();
|
|
void setImmutable();
|
|
Field getField();
|
|
PVStructure getParent();
|
|
void renameField(String newName);
|
|
void postPut(); // calls PVRecordField.postPut if this is a field of a record
|
|
void setPostHandler(PostHandler postHandler);
|
|
void toString(StringBuilder buf);
|
|
void toString(StringBuilder buf,int indentLevel);
|
|
String toString();
|
|
}</pre>
|
|
<h4>pvDataCPP</h4>
|
|
<pre>class PVField
|
|
: virtual public Serializable,
|
|
public std::tr1::enable_shared_from_this<PVField>
|
|
{
|
|
public:
|
|
POINTER_DEFINITIONS(PVField);
|
|
virtual ~PVField();
|
|
virtual void message(String message,MessageType messageType);
|
|
String getFieldName() const ;
|
|
virtual void setRequester(RequesterPtr const &prequester);
|
|
std::size_t getFieldOffset() const;
|
|
std::size_t getNextFieldOffset() const;
|
|
std::size_t getNumberFields() const;
|
|
PVAuxInfoPtr & getPVAuxInfo()
|
|
bool isImmutable() const;
|
|
virtual void setImmutable();
|
|
const FieldConstPtr & getField() const ;
|
|
PVStructure * getParent() const
|
|
void replacePVField(const PVFieldPtr& newPVField);
|
|
void renameField(String const &newName);
|
|
void postPut() ;
|
|
void setPostHandler(PostHandlerPtr const &postHandler);
|
|
virtual bool equals(PVField &pv);
|
|
virtual void toString(StringBuilder buf) ;
|
|
virtual void toString(StringBuilder buf,int indentLevel);
|
|
virtual std::ostream& dumpValue(std::ostream& o) const =0;
|
|
...
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f);
|
|
</pre>
|
|
<h4>pvDataCPP-md</h4>
|
|
<pre>class PVField
|
|
: virtual public Serializable,
|
|
public std::tr1::enable_shared_from_this<PVField>
|
|
{
|
|
public:
|
|
POINTER_DEFINITIONS(PVField);
|
|
virtual ~PVField();
|
|
virtual void message(String message,MessageType messageType);
|
|
String getFieldName() const ;
|
|
virtual void setRequester(RequesterPtr const &prequester);
|
|
std::size_t getFieldOffset() const;
|
|
std::size_t getNextFieldOffset() const;
|
|
std::size_t getNumberFields() const;
|
|
PVAuxInfoPtr & getPVAuxInfo()
|
|
bool isImmutable() const;
|
|
virtual void setImmutable();
|
|
const FieldConstPtr & getField() const ;
|
|
PVStructure * getParent() const
|
|
void replacePVField(const PVFieldPtr& newPVField);
|
|
void renameField(String const &newName);
|
|
void postPut() ;
|
|
void setPostHandler(PostHandlerPtr const &postHandler);
|
|
virtual bool equals(PVField &pv);
|
|
virtual void toString(StringBuilder buf) ;
|
|
virtual void toString(StringBuilder buf,int indentLevel);
|
|
std::ostream& dumpValue(std::ostream& o) const;
|
|
// not in pvDataCPP
|
|
String getFullName() const;
|
|
...
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f);
|
|
</pre>
|
|
<h4>proposed</h4>
|
|
<pre>
|
|
class PVField
|
|
: virtual public Serializable,
|
|
public std::tr1::enable_shared_from_this<PVField>
|
|
{
|
|
public:
|
|
POINTER_DEFINITIONS(PVField);
|
|
virtual ~PVField();
|
|
virtual void message(String message,MessageType messageType);
|
|
const String& getFieldName() const;
|
|
virtual void setRequester(RequesterPtr const &prequester);
|
|
std::size_t getFieldOffset() const;
|
|
std::size_t getNextFieldOffset() const;
|
|
std::size_t getNumberFields() const;
|
|
PVAuxInfoPtr & getPVAuxInfo();
|
|
bool isImmutable() const;
|
|
void setImmutable();
|
|
const FieldConstPtr & getField() const;
|
|
PVStructure * getParent() const;
|
|
void replacePVField(const PVFieldPtr& newPVField);
|
|
void renameField(String const & newName);
|
|
void postPut();
|
|
void setPostHandler(PostHandlerPtr const &postHandler);
|
|
virtual bool equals(PVField &pv);
|
|
void toString(StringBuilder buf) ;
|
|
void toString(StringBuilder buf,int indentLevel);
|
|
std::ostream& operator<<(std::ostream& o) const;
|
|
...
|
|
};
|
|
|
|
</pre>
|
|
<h3>PVScalar</h3>
|
|
<p>The Java and pvDataCPP versions differ in that Java has an interface definition
|
|
for each scalar type, i. e. PVBoolean, ..., PVString,
|
|
and the CPP versions provide a template PVValue for the implementation.</p>
|
|
<p>
|
|
pvDataCPP-md differs from pvDataCPP in that it implements three additional
|
|
methods:
|
|
<dl>
|
|
<dt>getAs</dt>
|
|
<dd>This is used to implement the Convert::toXXX methods.
|
|
This belongs in the Convert implementation not in PVScalar.</dd>
|
|
<dt>putFrom</dt>
|
|
<dd>This is used to implement the Convert::fromXXX scalar methods.
|
|
This belongs in the Convert implementation not in PVScalar.</dd>
|
|
<dt>assign</dt>
|
|
<dd>This does the same thing as the Convert::fromXXX methods except
|
|
that it does not go through Convert.
|
|
This belongs in the Convert implementation not in PVScalar.</dd>
|
|
</dl>
|
|
</p>
|
|
<p>The proposed version is like the pvDataCPP version except for dumpValue
|
|
and the stream interators.</p>
|
|
<h4>pvDataJava</h4>
|
|
<pre>
|
|
interface PVScalar extends PVField {
|
|
Scalar getScalar();
|
|
}
|
|
|
|
interface PVBoolean extends PVScalar {
|
|
boolean get();
|
|
void put(boolean value);
|
|
}
|
|
|
|
interface PVByte extends PVScalar {
|
|
byte get();
|
|
void put(byte value);
|
|
}
|
|
...
|
|
interface PVDouble extends PVScalar {
|
|
double get();
|
|
void put(double value);
|
|
}
|
|
interface PVString extends PVScalar, SerializableArray {
|
|
String get();
|
|
void put(String value);
|
|
}
|
|
</pre>
|
|
<h4>pvDataCPP</h4>
|
|
<pre>class PVScalar : public PVField {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalar);
|
|
virtual ~PVScalar();
|
|
typedef PVScalar &reference;
|
|
typedef const PVScalar& const_reference;
|
|
const ScalarConstPtr getScalar() const ;
|
|
...
|
|
}
|
|
|
|
template<typename T>
|
|
class PVScalarValue : public PVScalar {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalarValue);
|
|
typedef T value_type;
|
|
typedef T* pointer;
|
|
typedef const T* const_pointer;
|
|
virtual ~PVScalarValue() {}
|
|
virtual T get() const = 0;
|
|
virtual void put(T value) = 0;
|
|
std::ostream& dumpValue(std::ostream& o) const
|
|
void operator>>=(T& value) const;
|
|
void operator<<=(T value);
|
|
...
|
|
}
|
|
|
|
typedef PVScalarValue<uint8> PVBoolean;
|
|
typedef PVScalarValue<int8> PVByte;
|
|
...typedef PVScalarValue<double> PVDouble;
|
|
typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
|
|
typedef std::tr1::shared_ptr<PVByte> PVBytePtr;
|
|
...
|
|
typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
|
|
|
|
|
|
// PVString is special case, since it implements SerializableArray
|
|
class PVString : public PVScalarValue<String>, SerializableArray {
|
|
public:
|
|
virtual ~PVString() {}
|
|
...
|
|
};</pre>
|
|
|
|
<h4>pvDataCPP-md</h4>
|
|
<pre>class PVScalar : public PVField {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalar);
|
|
virtual ~PVScalar();
|
|
typedef PVScalar &reference;
|
|
typedef const PVScalar& const_reference;
|
|
const ScalarConstPtr getScalar() const ;
|
|
|
|
// not in pvDataCPP
|
|
template<ScalarType ID>
|
|
inline typename ScalarTypeTraits<ID>::type getAs() const;
|
|
|
|
virtual void getAs(void *, ScalarType) const = 0;
|
|
template<ScalarType ID>
|
|
inline void putFrom(typename ScalarTypeTraits<ID>::type val)
|
|
|
|
virtual void putFrom(const void *, ScalarType) = 0;
|
|
virtual void assign(const PVScalar&) = 0;
|
|
|
|
...
|
|
}
|
|
|
|
template<typename T>
|
|
class PVScalarValue : public PVScalar {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalarValue);
|
|
typedef T value_type;
|
|
typedef T* pointer;
|
|
typedef const T* const_pointer;
|
|
virtual ~PVScalarValue() {}
|
|
virtual T get() const = 0;
|
|
virtual void put(T value) = 0;
|
|
std::ostream& dumpValue(std::ostream& o) const
|
|
void operator>>=(T& value) const;
|
|
void operator<<=(T value);
|
|
|
|
// not in pvDataCPP
|
|
static const ScalarType typeCode;
|
|
...
|
|
}
|
|
|
|
typedef PVScalarValue<uint8> PVBoolean;
|
|
typedef PVScalarValue<int8> PVByte;
|
|
...typedef PVScalarValue<double> PVDouble;
|
|
typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
|
|
typedef std::tr1::shared_ptr<PVByte> PVBytePtr;
|
|
...
|
|
typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
|
|
|
|
|
|
// PVString is special case, since it implements SerializableArray
|
|
class PVString : public PVScalarValue<String>, SerializableArray {
|
|
public:
|
|
virtual ~PVString() {}
|
|
...
|
|
};</pre>
|
|
<h4>proposed</h4>
|
|
<pre>
|
|
class PVScalar : public PVField {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalar);
|
|
virtual ~PVScalar();
|
|
|
|
typedef PVScalar &reference;
|
|
typedef const PVScalar& const_reference;
|
|
|
|
const ScalarConstPtr getScalar() const;
|
|
...
|
|
};
|
|
|
|
template<typename T>
|
|
class PVScalarValue : public PVScalar {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalarValue);
|
|
typedef T value_type;
|
|
typedef T* pointer;
|
|
typedef const T* const_pointer;
|
|
|
|
virtual ~PVScalarValue() {}
|
|
virtual T get() const = 0;
|
|
virtual void put(T value) = 0;
|
|
|
|
void operator>>=(T& value) const;
|
|
void operator<<=(T value);
|
|
...
|
|
};
|
|
typedef PVScalarValue<uint8> PVBoolean;
|
|
typedef PVScalarValue<int8> PVByte;
|
|
typedef PVScalarValue<double> PVDouble;
|
|
...
|
|
typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
|
|
typedef std::tr1::shared_ptr<PVByte> PVBytePtr;
|
|
...
|
|
typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
|
|
|
|
// PVString is special case, since it implements SerializableArray
|
|
class PVString : public PVScalarValue<String>, SerializableArray {
|
|
public:
|
|
virtual ~PVString() {}
|
|
...
|
|
};
|
|
</pre>
|
|
<h3>PVArray</h3>
|
|
<p>The Java and pvDataCPP versions differ in that Java has an interface definition
|
|
for each scalarArray type, i. e. PVBooleanArray, ..., PVStringArray,
|
|
and the CPP versions provide a template PVValueArray for the implementation.</p>
|
|
<p>
|
|
pvDataCPP-md differs from pvDataCPP in that it implements additional
|
|
methods:
|
|
<dl>
|
|
<dt>getAs</dt>
|
|
<dd>This is used to implement the Convert::toXXXArray methods.
|
|
This belongs in the Convert implementation not in PVArray.</dd>
|
|
<dt>putFrom</dt>
|
|
<dd>This is used to implement the Convert::fromXXXArray scalar methods.
|
|
This belongs in the Convert implementation not in PVArray.</dd>
|
|
<dt>assign</dt>
|
|
<dd>This does the same thing as the Convert::fromXXXArray methods except
|
|
that it does not go through Convert.
|
|
This belongs in the Convert implementation not in PVArray.</dd>
|
|
<dt>copyOut</dt>
|
|
<dd>This is used to copy data to a raw array.</dd>
|
|
<dt>copyIn</dt>
|
|
<dd>This is used to copy data in from a raw array.</dt>
|
|
</dl>
|
|
</p>
|
|
<p>The proposed version is differs from pvJava, pvDataCPP, and pvCPP-md.
|
|
It is like the Java version if the Java get method is simplified as discussed above.
|
|
For example PVDoubleArray::get becomes:
|
|
<pre>
|
|
double[] get();
|
|
</pre>
|
|
The corresponding C++ version becomes:
|
|
<pre>
|
|
const svector & get();
|
|
const const_svector & get() const;
|
|
</pre>
|
|
</p>
|
|
<p>The remaining difference is that dumpValue is replaced by the stream operator<<. </p>
|
|
<p>The main difference from the pvDataJava version is that PVValueArray "wraps" shared_vector.
|
|
Thus shared_vector takes the place of the raw arrays in Java.
|
|
This allows the C++ interface to be more similar to Java.</p>
|
|
<p>The main difference from the pvDataCPP-md version is that it does not implement
|
|
the extra methods and allows
|
|
the client access to the shared_vector.
|
|
The client is then able to perform C++ specific things to the data.
|
|
BUT it also means that if the client modifies the shared_vector
|
|
the client is also responsible for ensuring that the
|
|
immutable and capacity related features of PVField and PVArray are
|
|
respected and the postPut is properly handled.
|
|
</p>
|
|
<p>Note that two get methods exist.
|
|
One allows write access to the raw data and the other doesn't/</p>
|
|
<h4>pvDataJava</h4>
|
|
<pre>interface PVArray extends PVField, SerializableArray {
|
|
int getLength();
|
|
void setLength(int length);
|
|
int getCapacity();
|
|
void setCapacity(int length);
|
|
boolean isCapacityMutable();
|
|
void setCapacityMutable(boolean isMutable);
|
|
}
|
|
|
|
interface PVScalarArray extends PVArray {
|
|
ScalarArray getScalarArray();
|
|
}</pre>
|
|
<p>For each scalar type an associated array data interface is defined. Each has
|
|
a get and put method. For example: </p>
|
|
<pre>public class DoubleArrayData {
|
|
public double[] data;
|
|
public int offset;
|
|
}
|
|
|
|
interface PVDoubleArray extends PVArray {
|
|
int get(int offset, int len, DoubleArrayData data);
|
|
int put(int offset,int len, double[] from, int fromOffset);
|
|
void shareData(double[] from);
|
|
}</pre>
|
|
<h4>pvDataCPP</h4>
|
|
<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;
|
|
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
|
|
|
|
...
|
|
};
|
|
|
|
|
|
template<typename T>
|
|
class PVArrayData {
|
|
private:
|
|
std::vector<T> init;
|
|
public:
|
|
POINTER_DEFINITIONS(PVArrayData);
|
|
typedef T value_type;
|
|
typedef T* pointer;
|
|
typedef const T* const_pointer;
|
|
std::vector<T> & data;
|
|
std::size_t offset;
|
|
PVArrayData()
|
|
: data(init)
|
|
{}
|
|
};
|
|
|
|
class PVScalarArray : public PVArray {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalarArray);
|
|
virtual ~PVScalarArray();
|
|
typedef PVScalarArray &reference;
|
|
typedef const PVScalarArray& const_reference;
|
|
const ScalarArrayConstPtr getScalarArray() const ;
|
|
...
|
|
}
|
|
|
|
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;
|
|
|
|
...
|
|
};
|
|
|
|
/**
|
|
* Definitions for the various scalarArray types.
|
|
*/
|
|
typedef PVArrayData<uint8> BooleanArrayData;
|
|
typedef PVValueArray<uint8> PVBooleanArray;
|
|
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
|
|
...
|
|
typedef PVArrayData<String> StringArrayData;
|
|
typedef PVValueArray<String> PVStringArray;
|
|
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;i
|
|
</pre>
|
|
|
|
<h4>pvDataCPP-md</h4>
|
|
<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;
|
|
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
|
|
...
|
|
};
|
|
|
|
std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array);
|
|
|
|
template<typename T>
|
|
class PVArrayData {
|
|
private:
|
|
std::vector<T> init;
|
|
public:
|
|
POINTER_DEFINITIONS(PVArrayData);
|
|
typedef T value_type;
|
|
typedef T* pointer;
|
|
typedef const T* const_pointer;
|
|
std::vector<T> & data;
|
|
std::size_t offset;
|
|
PVArrayData()
|
|
: data(init)
|
|
{}
|
|
};
|
|
|
|
class PVScalarArray : public PVArray {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalarArray);
|
|
virtual ~PVScalarArray();
|
|
typedef PVScalarArray &reference;
|
|
typedef const PVScalarArray& const_reference;
|
|
const ScalarArrayConstPtr getScalarArray() const ;
|
|
|
|
// in pvDataCPP but not in pvDataCPP=md
|
|
//virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
|
|
|
|
// not in pvDataCPP
|
|
template<ScalarType ID>
|
|
virtual void
|
|
getAs(shared_vector<typename ScalarTypeTraits<ID>::type>& out) const;
|
|
|
|
virtual void
|
|
getAs(ScalarType, shared_vector<void>& out) const = 0;
|
|
|
|
template<ScalarType ID>
|
|
inline size_t copyOut(typename ScalarTypeTraits<ID>::type* inp, size_t len) const;
|
|
|
|
virtual size_t copyOut(ScalarType id, void* ptr, size_t olen) const = 0;
|
|
|
|
template<ScalarType ID>
|
|
inline void putFrom(const shared_vector<typename ScalarTypeTraits<ID>::type>& inp);
|
|
|
|
virtual void putFrom(ScalarType, const shared_vector<void>&) = 0;
|
|
|
|
template<ScalarType ID>
|
|
inline void copyIn(const typename ScalarTypeTraits<ID>::type* inp, size_t len);
|
|
|
|
virtual void copyIn(ScalarType, const void*, size_t) = 0;
|
|
|
|
virtual void assign(PVScalarArray& pv) = 0;
|
|
|
|
...
|
|
}
|
|
|
|
template<typename T>
|
|
class PVValueArray : public detail::PVVectorStorage<T,PVScalarArray> {
|
|
typedef detail::PVVectorStorage<T,PVScalarArray> base_t;
|
|
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;
|
|
|
|
/// not in pvDataCPP
|
|
static const ScalarType typeCode;
|
|
typedef ::epics::pvData::shared_vector<T> svector;
|
|
typedef ::epics::pvData::shared_vector<const T> const_svector;
|
|
|
|
virtual void
|
|
getAs(ScalarType id, ::epics::pvData::shared_vector<void>& out) const;
|
|
virtual size_t copyOut(ScalarType id, void* ptr, size_t olen) const;
|
|
virtual void
|
|
putFrom(ScalarType id, const ::epics::pvData::shared_vector<void>& inp);
|
|
virtual void copyIn(ScalarType id, const void* ptr, size_t len);
|
|
virtual void assign(PVScalarArray& pv);
|
|
|
|
|
|
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<String> StringArrayData;
|
|
typedef PVValueArray<String> PVStringArray;
|
|
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;i
|
|
</pre>
|
|
<h4>proposed</h4>
|
|
<pre>class PVArray : public PVField, public SerializableArray {
|
|
public:
|
|
POINTER_DEFINITIONS(PVArray);
|
|
virtual ~PVArray();
|
|
virtual std::size_t getLength() const = 0;
|
|
virtual void setLength(std::size_t length) = 0;
|
|
bool isCapacityMutable() const;
|
|
void setCapacityMutable(bool isMutable);
|
|
virtual std::size_t getCapacity() const = 0;
|
|
virtual void setCapacity(std::size_t capacity) = 0;
|
|
...
|
|
};
|
|
|
|
|
|
class PVScalarArray : public PVArray {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalarArray);
|
|
typedef PVScalarArray &reference;
|
|
typedef const PVScalarArray& const_reference;
|
|
|
|
virtual ~PVScalarArray();
|
|
const ScalarArrayConstPtr getScalarArray() const;
|
|
...
|
|
};
|
|
|
|
template<typename T>
|
|
class PVValueArray : public PVScalarArray
|
|
{
|
|
public:
|
|
POINTER_DEFINITIONS(PVValueArray);
|
|
typedef T value_type;
|
|
typedef T* pointer;
|
|
typedef const T* const_pointer;
|
|
typedef PVValueArray & reference;
|
|
typedef const PVValueArray & const_reference;
|
|
|
|
typedef shared_vector<T> svector;
|
|
typedef shared_vector<const T> const_svector;
|
|
|
|
virtual ~PVValueArray() {}
|
|
const svector & get() ;
|
|
const const_svector &get() const;
|
|
size_t put(size_t offset,size_t length, const_pointer from, size_t fromOffset);
|
|
|
|
void shareData(const svector &from);
|
|
|
|
...
|
|
};
|
|
|
|
typedef PVValueArray<uint8> PVBooleanArray;
|
|
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
|
|
...
|
|
typedef PVValueArray<String> PVStringArray;
|
|
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
|
|
</pre>
|
|
|
|
|
|
|
|
<h2>pvDataApp/pv</h2>
|
|
<h3>pvData.h</h3>
|
|
<p>This provides the interface for network accessible data.
|
|
Although templates are used to minimize the amount of code,
|
|
the interface is <b>not</b> meant to be extended.
|
|
Only the types defined by pvIntrospect are implemented.</p>
|
|
|
|
<h4>PVField</h4>
|
|
<pre>
|
|
class PVField
|
|
: virtual public Serializable,
|
|
public std::tr1::enable_shared_from_this<PVField>
|
|
{
|
|
public:
|
|
POINTER_DEFINITIONS(PVField);
|
|
virtual ~PVField();
|
|
virtual void message(String message,MessageType messageType);
|
|
const String& getFieldName() const;
|
|
virtual void setRequester(RequesterPtr const &prequester);
|
|
std::size_t getFieldOffset() const;
|
|
std::size_t getNextFieldOffset() const;
|
|
std::size_t getNumberFields() const;
|
|
PVAuxInfoPtr & getPVAuxInfo();
|
|
bool isImmutable() const;
|
|
void setImmutable();
|
|
const FieldConstPtr & getField() const;
|
|
PVStructure * getParent() const;
|
|
void replacePVField(const PVFieldPtr& newPVField);
|
|
void renameField(String const & newName);
|
|
void postPut();
|
|
void setPostHandler(PostHandlerPtr const &postHandler);
|
|
virtual bool equals(PVField &pv);
|
|
void toString(StringBuilder buf) ;
|
|
void toString(StringBuilder buf,int indentLevel);
|
|
std::ostream& operator<<(std::ostream& o) const;
|
|
...
|
|
};
|
|
|
|
std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f);
|
|
std::ostream& operator<<(std::ostream& o, const PVFieldPtr & f, size_t index);
|
|
</pre>
|
|
<p>The public methods for PVField are:</p>
|
|
<dl>
|
|
<dt>~PVField</dt>
|
|
<dd>Destructor. Since shared pointers are used it should never be called by
|
|
user code.</dd>
|
|
<dt>message</dt>
|
|
<dd>Code attached to this field can call this method to report
|
|
problems.</dd>
|
|
<dt>getFieldName</dt>
|
|
<dd>Get the field name. If the field is a top level structure the field
|
|
name will be an empty string.</dd>
|
|
<dt>setRequester</dt>
|
|
<dd>Sets a requester to be called when message or getRequesterName are
|
|
called. This is only legal for the top level PVField. </dd>
|
|
<dt>getFieldOffset</dt>
|
|
<dd>Get offset of the PVField field within top level structure. Every field
|
|
within the PVStructure has a unique offset. The top level structure has
|
|
an offset of 0. The first field within the structure has offset equal to
|
|
1. The other offsets are determined by recursively traversing each
|
|
structure of the tree. </dd>
|
|
<dt>getNextFieldOffset</dt>
|
|
<dd>Get the next offset. If the field is a scalar or array field then this
|
|
is just offset + 1. If the field is a structure it is the offset of the
|
|
next field after this structure. Thus (nextOffset - offset) is always
|
|
equal to the total number of fields within the field. </dd>
|
|
<dt>getNumberFields</dt>
|
|
<dd>Get the total number of fields in this field. This is nextFieldOffset -
|
|
fieldOffset. </dd>
|
|
<dt>getPVAuxInfo</dt>
|
|
<dd>Get the PVAuxInfo for this field. PVAuxInfo is described below.</dd>
|
|
<dt>isImmutable</dt>
|
|
<dd>Is the field immutable?</dd>
|
|
<dt>setImmutable</dt>
|
|
<dd>Make the field immutable. Once a field is immutable it can never be
|
|
changed since there is no method to again make it mutable. This is an
|
|
important design decision since it allows immutable array fields to share
|
|
the internal primitive data array.</dd>
|
|
<dt>getField</dt>
|
|
<dd>Get the reflection interface for the data.</dd>
|
|
<dt>getParent</dt>
|
|
<dd>Get the interface for the parent or null if this is the top level
|
|
PVStructure.</dd>
|
|
<dt>replacePVField</dt>
|
|
<dd>Replace the data implementation for the field.</dd>
|
|
<dt>renameField</dt>
|
|
<dd>Rename the field name. </dd>
|
|
<dt>postPut</dt>
|
|
<dd>If a postHandler is registered it is called otherwise no action is
|
|
taken.</dd>
|
|
<dt>setPostHandler</dt>
|
|
<dd>Set the postHandler for the record. Only a single handler can be
|
|
registered.</dd>
|
|
<dt>operator<<</dt>
|
|
<dd>Stream output</dt>
|
|
</dl>
|
|
<h4>PVScalar</h4>
|
|
<pre>
|
|
class PVScalar : public PVField {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalar);
|
|
virtual ~PVScalar();
|
|
|
|
typedef PVScalar &reference;
|
|
typedef const PVScalar& const_reference;
|
|
|
|
const ScalarConstPtr getScalar() const;
|
|
...
|
|
};
|
|
</pre>
|
|
<p>where</p>
|
|
<dl>
|
|
<dt>getScalar</dt>
|
|
<dd>Get the introspection interface for the PVScalar.</dd>
|
|
</dl>
|
|
|
|
<h4>PVScalarValue</h4>
|
|
<pre>
|
|
template<typename T>
|
|
class PVScalarValue : public PVScalar {
|
|
public:
|
|
POINTER_DEFINITIONS(PVScalarValue);
|
|
typedef T value_type;
|
|
typedef T* pointer;
|
|
typedef const T* const_pointer;
|
|
|
|
virtual ~PVScalarValue() {}
|
|
virtual T get() const = 0;
|
|
virtual void put(T value) = 0;
|
|
void operator>>=(T& value) const;
|
|
void operator<<=(T value);
|
|
...
|
|
};
|
|
typedef PVScalarValue<uint8> PVBoolean;
|
|
typedef PVScalarValue<int8> PVByte;
|
|
typedef PVScalarValue<int16> PVShort;
|
|
typedef PVScalarValue<int32> PVInt;
|
|
typedef PVScalarValue<int64> PVLong;
|
|
typedef PVScalarValue<uint8> PVUByte;
|
|
typedef PVScalarValue<uint16> PVUShort;
|
|
typedef PVScalarValue<uint32> PVUInt;
|
|
typedef PVScalarValue<uint64> PVULong;
|
|
typedef PVScalarValue<float> PVFloat;
|
|
typedef PVScalarValue<double> PVDouble;
|
|
typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
|
|
typedef std::tr1::shared_ptr<PVByte> PVBytePtr;
|
|
typedef std::tr1::shared_ptr<PVShort> PVShortPtr;
|
|
typedef std::tr1::shared_ptr<PVInt> PVIntPtr;
|
|
typedef std::tr1::shared_ptr<PVLong> PVLongPtr;
|
|
typedef std::tr1::shared_ptr<PVUByte> PVUBytePtr;
|
|
typedef std::tr1::shared_ptr<PVUShort> PVUShortPtr;
|
|
typedef std::tr1::shared_ptr<PVUInt> PVUIntPtr;
|
|
typedef std::tr1::shared_ptr<PVULong> PVULongPtr;
|
|
typedef std::tr1::shared_ptr<PVFloat> PVFloatPtr;
|
|
typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;
|
|
|
|
// PVString is special case, since it implements SerializableArray
|
|
class PVString : public PVScalarValue<String>, SerializableArray {
|
|
public:
|
|
virtual ~PVString() {}
|
|
...
|
|
};
|
|
</pre>
|
|
|
|
<p>where</p>
|
|
<dl>
|
|
<dt>get</dt>
|
|
<dd>Get the value stored in the object.</dd>
|
|
<dt>put</dt>
|
|
<dd>Change the value stored in the object.</dd>
|
|
<dt>operator<<</dt>
|
|
<dt>operator>></dt>
|
|
<dd>Methods for stream I/O.</dd>
|
|
</dl>
|
|
|
|
|
|
<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 std::size_t getLength() const = 0;
|
|
virtual void setLength(std::size_t length) = 0;
|
|
bool isCapacityMutable() const;
|
|
void setCapacityMutable(bool isMutable);
|
|
virtual std::size_t getCapacity() const = 0;
|
|
virtual void setCapacity(std::size_t capacity) = 0;
|
|
...
|
|
};</pre>
|
|
<dl>
|
|
<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>isCapacityMutable</dt>
|
|
<dd>Is the capacity mutable</dd>
|
|
<dt>setCapacityMutable</dt>
|
|
<dd>Specify if the capacity can be changed.</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>
|
|
</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);
|
|
typedef PVScalarArray &reference;
|
|
typedef const PVScalarArray& const_reference;
|
|
|
|
virtual ~PVScalarArray();
|
|
const ScalarArrayConstPtr getScalarArray() const;
|
|
...
|
|
};
|
|
</pre>
|
|
|
|
<p>where</p>
|
|
<dl>
|
|
<dt>getScalarArray</dt>
|
|
<dd>Get the introspection interface.</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 PVValueArray & reference;
|
|
typedef const PVValueArray & const_reference;
|
|
|
|
typedef shared_vector<T> svector;
|
|
typedef shared_vector<const T> const_svector;
|
|
|
|
virtual ~PVValueArray() {}
|
|
const svector & get() ;
|
|
const const_svector &get() const;
|
|
size_t put(size_t offset,size_t length, const_pointer from, size_t fromOffset);
|
|
|
|
void shareData(const svector &from);
|
|
...
|
|
};
|
|
|
|
typedef PVValueArray<uint8> PVBooleanArray;
|
|
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
|
|
|
|
typedef PVValueArray<int8> PVByteArray;
|
|
typedef std::tr1::shared_ptr<PVByteArray> PVByteArrayPtr;
|
|
|
|
typedef PVValueArray<int16> PVShortArray;
|
|
typedef std::tr1::shared_ptr<PVShortArray> PVShortArrayPtr;
|
|
|
|
typedef PVValueArray<int32> PVIntArray;
|
|
typedef std::tr1::shared_ptr<PVIntArray> PVIntArrayPtr;
|
|
|
|
typedef PVValueArray<int64> PVLongArray;
|
|
typedef std::tr1::shared_ptr<PVLongArray> PVLongArrayPtr;
|
|
|
|
typedef PVValueArray<uint8> PVUByteArray;
|
|
typedef std::tr1::shared_ptr<PVUByteArray> PVUByteArrayPtr;
|
|
|
|
typedef PVValueArray<uint16> PVUShortArray;
|
|
typedef std::tr1::shared_ptr<PVUShortArray> PVUShortArrayPtr;
|
|
|
|
typedef PVValueArray<uint32> PVUIntArray;
|
|
typedef std::tr1::shared_ptr<PVUIntArray> PVUIntArrayPtr;
|
|
|
|
typedef PVValueArray<uint64> PVULongArray;
|
|
typedef std::tr1::shared_ptr<PVULongArray> PVULongArrayPtr;
|
|
|
|
typedef PVValueArray<float> PVFloatArray;
|
|
typedef std::tr1::shared_ptr<PVFloatArray> PVFloatArrayPtr;
|
|
|
|
typedef PVValueArray<double> PVDoubleArray;
|
|
typedef std::tr1::shared_ptr<PVDoubleArray> PVDoubleArrayPtr;
|
|
|
|
typedef PVValueArray<String> PVStringArray;
|
|
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
|
|
</pre>
|
|
|
|
<p>where</p>
|
|
<dl>
|
|
<dt>get</dt>
|
|
<dd>Get the shared_vector that holds the data.
|
|
Code that calls this is able to modify the array elements
|
|
but should be very careful if it does.
|
|
For example it must call postPut after modifying the array elements.
|
|
It must also respect isImmutable().
|
|
</dd>
|
|
<dt>size_t put(size_t offset,size_t length, const_pointer from, size_t fromOffset);</dt>
|
|
<dt>put</dt>
|
|
<dd>This is the recommended method for modifying the array elements.
|
|
It may change the capacity if len asks for more elements
|
|
than the cureent capacity allows.
|
|
It does not change the current length.
|
|
</dd>
|
|
<dt>shareData</dt>
|
|
<dd>Share data with an existing shared_vector.
|
|
Note that if capacity is ever changed then data will no
|
|
longer be shared.
|
|
This method can also be called to force the PVValueArray to have a new
|
|
raw array. This is usefull for implementing Copy On Write.
|
|
</dd>
|
|
</dl>
|
|
|
|
<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>
|
|
<p>When <b>NOTE EXISTING</b> appears it means that there is a question about
|
|
the existing shared_vector implementation.</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>NOTE: data</b> The above code is better implemented as:</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 be ((size_t)-1)/sizeof(T)
|
|
</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>
|
|
is guaranteed to be the same as
|
|
<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>
|
|
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|