Merge branch 'shared-vector'
This commit is contained in:
1621
documentation/Doxyfile
Normal file
1621
documentation/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
1842
documentation/pvArray.html
Normal file
1842
documentation/pvArray.html
Normal file
File diff suppressed because it is too large
Load Diff
792
documentation/pvDataDiscussion.html
Normal file
792
documentation/pvDataDiscussion.html
Normal file
@@ -0,0 +1,792 @@
|
||||
<?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 pvDataDiscussion</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 pvDataDiscussion</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 03-Jul-2013</h2>
|
||||
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDataCPP/raw-file/tip/documentation/pvDataDiscussion.html">pvDataDiscussion.html</a>
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd>none</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd>None</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, 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>As pvDataCPP progressed PVField and derived classes accumulated
|
||||
more and more member functions.
|
||||
These member functions have nothing to do with the primary 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 it clear that communication
|
||||
includes efficent network communication.
|
||||
Thus pvData provides an interface for network accessible structured data.
|
||||
The problem of adding member functions that have nothing to do with the primary purpose
|
||||
started with the Java API.
|
||||
It already had extra methods that solved problems that should have had a different solution.
|
||||
This document removes the extra methods so that when new problems arise in the future
|
||||
the solution will not involve adding new member functions to the introspection and data API.
|
||||
</p>
|
||||
<p>The introspection and data API for pvData should only encapuslate methods that support the primary purpose
|
||||
stated above.
|
||||
The interfaces for C++ and Java should be similar so that
|
||||
someone who understands the interface in one of the languages
|
||||
and knows both languages will quickly understand the interface of the other language.</p>
|
||||
<p>There is another problem with the existing API. There are methods that allow the "structure"
|
||||
to change after an pvData object is created. An example is PVField::renameField(String newName).
|
||||
Such methods should not exist.</p>
|
||||
<p>There are methods regarding immutability: setImmutable, isImmutablei, setCapacityMutable, and isCapacityMutable.
|
||||
Should they exists? For now lets assume no.
|
||||
</p>
|
||||
<p>One last issue is the interface for array data. This document proposes a simplified
|
||||
version of what currently exists. It requires that the implementation always provides storage for
|
||||
the complete raw array. The existing APIs allow the implementation to provide the data in
|
||||
"chunks". Giving up this requirement simplifies the array interfaces.
|
||||
The existing C++ implementation of PVValueArray has serious problems.
|
||||
The shared_vector that is implemented in pvDataCP-md provides the solution to fixing
|
||||
the problems. This document describes an API that is very similar to the new Java API
|
||||
except that raw arrays are replaced by shared_vector.</p>
|
||||
<p>This document will first describe changes to the existing Java interfaces
|
||||
and then the corresponding C++ API.</p>
|
||||
<h2>Java API</h2>
|
||||
<p>The following shows which methods will be removed from the existing interfaces
|
||||
and what will be added.
|
||||
The methods to be removed are in <font color = "red">red</font>
|
||||
and methods to add are in <font color = "blue">blue</font>
|
||||
Also the removed methods are at the end with a comment above.
|
||||
The new methods also have a comment.
|
||||
</p>
|
||||
<h3>Introspection Interfaces</h3>
|
||||
|
||||
<pre>interface Field extends Serializable {
|
||||
String getId();
|
||||
Type getType();
|
||||
// following will be removed
|
||||
<font color = "red">void toString(StringBuilder buf);</font>
|
||||
<font color = "red">void toString(StringBuilder buf,int indentLevel);</font>
|
||||
<font color = "red">String toString();</font>
|
||||
}
|
||||
|
||||
<font color = "blue">
|
||||
// new interface
|
||||
interface FieldToString {
|
||||
String toString(Field field);
|
||||
}</font>
|
||||
|
||||
interface Scalar extends Field {
|
||||
ScalarType getScalarType();
|
||||
}
|
||||
|
||||
interface ScalarArray extends Field {
|
||||
ScalarType getElementType();
|
||||
}
|
||||
|
||||
interface Structure extends Field {
|
||||
Field getField(String fieldName);
|
||||
int getFieldIndex(String fieldName);
|
||||
Field[] getFields();
|
||||
Field getField(int fieldIndex);
|
||||
String[] getFieldNames();
|
||||
String getFieldName(int fieldIndex)
|
||||
}
|
||||
|
||||
interface StructureArray extends Field {
|
||||
Structure getStructure();
|
||||
}
|
||||
|
||||
interface FieldCreate {
|
||||
Scalar createScalar(ScalarType scalarType);
|
||||
ScalarArray createScalarArray(ScalarType elementType);
|
||||
StructureArray createStructureArray(Structure elementStructure);
|
||||
Structure createStructure(String[] fieldNames, Field[] field);
|
||||
Structure createStructure(String id,String[] fieldNames, Field[] field);
|
||||
Structure createStructure(Structure structToClone);
|
||||
Field deserialize(ByteBuffer buffer, DeserializableControl control);
|
||||
// following will be removed
|
||||
<font color = "red">Structure appendField(Structure structure,String fieldName, Field field);</font>
|
||||
<font color = "red">Structure appendFields(Structure structure,String[] fieldNames, Field[] fields);</font>
|
||||
}
|
||||
</pre>
|
||||
<h3>Data Interfaces</h3>
|
||||
<pre>
|
||||
interface PVField extends Requester, Serializable {
|
||||
String getFieldName();
|
||||
void setRequester(Requester requester);
|
||||
int getFieldOffset();
|
||||
int getNextFieldOffset();
|
||||
int getNumberFields();
|
||||
Field getField();
|
||||
PVStructure getParent();
|
||||
void postPut();
|
||||
void setPostHandler(PostHandler postHandler);
|
||||
// following will be removed
|
||||
<font color = "red">PVAuxInfo getPVAuxInfo();</font>
|
||||
<font color = "red">boolean isImmutable();</font>
|
||||
<font color = "red">void setImmutable();</font>
|
||||
<font color = "red">void renameField(String newName);</font>
|
||||
<font color = "red">void toString(StringBuilder buf);</font>
|
||||
<font color = "red">void toString(StringBuilder buf,int indentLevel);</font>
|
||||
<font color = "red">String toString();</font>
|
||||
}
|
||||
|
||||
<font color = "blue">
|
||||
// The following is a new interface
|
||||
interface PVFieldToString {
|
||||
String toString(PVField pvField);
|
||||
void setMaxInitialArrayElements(int num);
|
||||
void setMaxFinalArrayElements(int num);
|
||||
int getMaxInitialArrayElements();
|
||||
int getMaxFinalArrayElements();
|
||||
}</font>
|
||||
|
||||
interface PVScalar extends PVField{
|
||||
Scalar getScalar();
|
||||
}
|
||||
|
||||
interface PVDouble extends PVScalar{
|
||||
double get();
|
||||
void put(double value);
|
||||
}
|
||||
// also PVBoolean, PVByte, PVShort, PVInt, PVLong, PVFloat, and PVString
|
||||
|
||||
interface PVArray extends PVField, SerializableArray {
|
||||
int getLength();
|
||||
void setLength(int length);
|
||||
int getCapacity();
|
||||
void setCapacity(int length);
|
||||
// following will be removed
|
||||
<font color = "red">boolean isCapacityMutable();</font>
|
||||
<font color = "red">void setCapacityMutable(boolean isMutable);</font>
|
||||
}
|
||||
|
||||
interface PVScalarArray extends PVArray {
|
||||
ScalarArray getScalarArray();
|
||||
}
|
||||
|
||||
<font color = "red">
|
||||
//following will be removed
|
||||
public class DoubleArrayData {
|
||||
public double[] data;
|
||||
public int offset;
|
||||
}</font>
|
||||
|
||||
interface PVDoubleArray extends PVArray {
|
||||
// following are new
|
||||
<font color = "blue"> double[] get();</font>
|
||||
<font color = "blue"> void swap(double[] value);</font>
|
||||
//following will be removed
|
||||
<font color = "red"> int get(int offset, int len, DoubleArrayData data);</font>
|
||||
<font color = "red"> int put(int offset,int len, double[] from, int fromOffset)</font>;
|
||||
<font color = "red"> void shareData(double[] from);</font>
|
||||
}
|
||||
|
||||
// also PVBooleanArray, ..., PVStringArray
|
||||
|
||||
|
||||
interface PVStructure extends PVField , BitSetSerializable{
|
||||
Structure getStructure();
|
||||
PVField[] getPVFields();
|
||||
PVField getSubField(String fieldName);
|
||||
PVField getSubField(int fieldOffset);
|
||||
// The following are convenience methods
|
||||
PVBoolean getBooleanField(String fieldName);
|
||||
PVByte getByteField(String fieldName);
|
||||
PVShort getShortField(String fieldName);
|
||||
PVInt getIntField(String fieldName);
|
||||
PVLong getLongField(String fieldName);
|
||||
PVFloat getFloatField(String fieldName);
|
||||
PVDouble getDoubleField(String fieldName);
|
||||
PVString getStringField(String fieldName);
|
||||
PVScalarArray getScalarArrayField(String fieldName);
|
||||
PVStructureArray getStructureArrayField(String fieldName);
|
||||
PVStructure getStructureField(String fieldName);
|
||||
PVArray getArrayField(String fieldName,ScalarType elementType);
|
||||
// following will be removed
|
||||
<font color = "red"> void appendPVField(String fieldName,PVField pvField);</font>
|
||||
<font color = "red"> void appendPVFields(String[] fieldNames,PVField[] pvFields);</font>
|
||||
<font color = "red"> void removePVField(String fieldName);</font>
|
||||
<font color = "red"> void replacePVField(PVField oldPVField,PVField newPVField);</font>
|
||||
<font color = "red"> String getExtendsStructureName();</font>
|
||||
<font color = "red"> boolean putExtendsStructureName(String extendsStructureName);</font>
|
||||
<font color = "red"> public boolean checkValid();</font>
|
||||
}
|
||||
|
||||
<font color = "red">
|
||||
//following will be removed
|
||||
public class StructureArrayData {
|
||||
public PVStructure[] data;
|
||||
public int offset;
|
||||
}
|
||||
</font>
|
||||
|
||||
interface PVStructureArray extends PVArray{
|
||||
StructureArray getStructureArray();
|
||||
// following are new
|
||||
<font color = "blue"> PVStructure[] get();</font>
|
||||
<font color = "blue"> void swap(PVStructure[] value);</font>
|
||||
// following will be removed
|
||||
<font color = "red"> int get(int offset, int length, StructureArrayData data);</font>
|
||||
<font color = "red"> int put(int offset,int length, PVStructure[] from, int fromOffset);</font>
|
||||
<font color = "red"> void shareData(PVStructure[] from);</font>
|
||||
}
|
||||
|
||||
|
||||
public interface PVDataCreate {
|
||||
PVField createPVField(Field field);
|
||||
PVField createPVField(PVField fieldToClone);
|
||||
PVScalar createPVScalar(Scalar scalar);
|
||||
PVScalar createPVScalar(ScalarType fieldType);
|
||||
PVScalar createPVScalar(PVScalar scalarToClone);
|
||||
PVScalarArray createPVScalarArray(ScalarArray array);
|
||||
PVScalarArray createPVScalarArray(ScalarType elementType);
|
||||
PVScalarArray createPVScalarArray(PVScalarArray arrayToClone;
|
||||
PVStructureArray createPVStructureArray(StructureArray structureArray);
|
||||
PVStructure createPVStructure(Structure structure);
|
||||
PVStructure createPVStructure(String[] fieldNames,Field[] fields);
|
||||
PVStructure createPVStructure(PVStructure structToClone);
|
||||
// following will be removed
|
||||
<font color = "red">PVField[] flattenPVStructure(PVStructure pvStructure);</font>
|
||||
}
|
||||
</pre>
|
||||
<h3>PVFieldToString</h3>
|
||||
<p>In addition to toString this has methods to limit the number of array element to display.
|
||||
The existing Java implementation of toString displayed all elements.
|
||||
For large arrays this is not desirable.
|
||||
The new methods provide a way for the client to limit the number of elements.
|
||||
The default might be set to something like display up to 10 elements with 5 fron the beginning and 5 from the end.</p>
|
||||
<p>For C++ this can be a replacement for dumpValue.</p>
|
||||
<h3>PVBooleanArray, ..., PVStructureArray</h3>
|
||||
<p>The old get and put are replaced by two new and simpler methods:
|
||||
<dl>
|
||||
<dt>get</dt>
|
||||
<dd>Returns the raw array. If the client code modifies the elements in the array then
|
||||
the client must call postPut. The client also has to realize that if the raw array held by the PVXXXArray changes
|
||||
then the client is no longer sharing data
|
||||
<dt>swap</dt>
|
||||
<dd>This exchanges the old raw data with the new raw data.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<p>
|
||||
The method <b>setCapacity</b> will always create a new raw array and copy old data from the old to the new array.
|
||||
This is not true now since the implementation does not create a new array if the old capacity is equal to the requested capacity.
|
||||
</p>
|
||||
<h2>C++ API</h2>
|
||||
<p>The C++ class definitions are similar to the Java definitions with two main exceptions:
|
||||
<dl>
|
||||
<dt>toString</dt>
|
||||
<dd>In c++ this is replaced by std::ostream.</dd>
|
||||
<dt>raw array data</dt>
|
||||
<dd>Java supports array data like <b>double[]</b>
|
||||
The C++ replacement is shared_vector<double>, which is implemented
|
||||
in pvDataCPP-md.</dd
|
||||
</dl>
|
||||
<h3>Introspection Interfaces</h3>
|
||||
|
||||
<pre>
|
||||
class Field :
|
||||
virtual public Serializable,
|
||||
public std::tr1::enable_shared_from_this<Field>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Field);
|
||||
virtual ~Field();
|
||||
Type getType() const{return m_type;}
|
||||
virtual String getID() const = 0;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
<font color = "blue">
|
||||
// new function
|
||||
std::ostream &toString(Field::const_reference field, std::ostream& o);
|
||||
</font>
|
||||
|
||||
class Scalar : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(Scalar);
|
||||
virtual ~Scalar();
|
||||
typedef Scalar& reference;
|
||||
typedef const Scalar& const_reference;
|
||||
|
||||
ScalarType getScalarType() const {return scalarType;}
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableContol *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
virtual String getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
class ScalarArray : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ScalarArray);
|
||||
typedef ScalarArray& reference;
|
||||
typedef const ScalarArray& const_reference;
|
||||
|
||||
ScalarArray(ScalarType scalarType);
|
||||
ScalarType getElementType() const {return elementType;}
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf) const{toString(buf,0);}
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
virtual String getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class Structure : public Field {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Structure);
|
||||
typedef Structure& reference;
|
||||
typedef const Structure& const_reference;
|
||||
|
||||
std::size_t getNumberFields() const {return numberFields;}
|
||||
FieldConstPtr getField(String const & fieldName) const;
|
||||
FieldConstPtr getField(std::size_t index) const;
|
||||
std::size_t getFieldIndex(String const &fieldName) const;
|
||||
FieldConstPtrArray const & getFields() const {return fields;}
|
||||
StringArray const & getFieldNames() const;
|
||||
String getFieldName(std::size_t fieldIndex);
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
void renameField(std::size_t fieldIndex,String const &newName);
|
||||
virtual void toString(StringBuilder buf,int indentLevel) const;
|
||||
virtual String getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class StructureArray : public Field{
|
||||
public:
|
||||
POINTER_DEFINITIONS(StructureArray);
|
||||
typedef StructureArray& reference;
|
||||
typedef const StructureArray& const_reference;
|
||||
|
||||
StructureConstPtr getStructure() const {return pstructure;}
|
||||
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
|
||||
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void toString(StringBuilder buf,int indentLevel=0) const;
|
||||
virtual String getID() const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class FieldCreate {
|
||||
public:
|
||||
static FieldCreatePtr getFieldCreate();
|
||||
ScalarConstPtr createScalar(ScalarType scalarType) const
|
||||
ScalarArrayConstPtr createScalarArray(ScalarType elementType) const;
|
||||
StructureArrayConstPtr createStructureArray(StructureConstPtr const & structure) const;
|
||||
StructureConstPtr createStructure (
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
StructureConstPtr createStructure (
|
||||
String const &id,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
StructureConstPtr appendField(
|
||||
StructureConstPtr const & structure,
|
||||
String const &fieldName, FieldConstPtr const & field) const;
|
||||
StructureConstPtr appendFields(
|
||||
StructureConstPtr const & structure,
|
||||
StringArray const & fieldNames,
|
||||
FieldConstPtrArray const & fields) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
extern FieldCreatePtr getFieldCreate();
|
||||
</pre>
|
||||
<h3>Data Interfaces</h3>
|
||||
<pre>
|
||||
class PVField
|
||||
: virtual public Serializable,
|
||||
public std::tr1::enable_shared_from_this<PVField>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVField);
|
||||
virtual ~PVField();
|
||||
inline 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;
|
||||
const FieldConstPtr & getField() const ;
|
||||
PVStructure * getParent() const
|
||||
void postPut() ;
|
||||
void setPostHandler(PostHandlerPtr const &postHandler);
|
||||
// following will be removed
|
||||
<font color = "red">
|
||||
virtual void message(String message,MessageType messageType);
|
||||
void replacePVField(const PVFieldPtr& newPVField);
|
||||
String getFullName() const;
|
||||
virtual bool equals(PVField &pv);
|
||||
PVAuxInfoPtr & getPVAuxInfo()
|
||||
bool isImmutable() const;
|
||||
virtual void setImmutable();
|
||||
void replacePVField(const PVFieldPtr& newPVField);
|
||||
void renameField(String const &newName);
|
||||
virtual void toString(StringBuilder buf) ;
|
||||
virtual void toString(StringBuilder buf,int indentLevel);
|
||||
std::ostream& dumpValue(std::ostream& o) const;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
<font color = "blue">
|
||||
// The following is a new class
|
||||
class PVFieldToString {
|
||||
String toString(const PVFieldPtr &pvField);
|
||||
void setMaxInitialArrayElements(size_t num);
|
||||
void setMaxFinalArrayElements(size_t num);
|
||||
size_t getMaxInitialArrayElements();
|
||||
size_t getMaxFinalArrayElements();
|
||||
...
|
||||
}</font>
|
||||
|
||||
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;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
std::ostream& dumpValue(std::ostream& o)
|
||||
void operator>>=(T& value) const;
|
||||
void operator<<=(T value);
|
||||
</font>
|
||||
...
|
||||
}
|
||||
|
||||
// PVString is special case, since it implements SerializableArray
|
||||
class PVString : public PVScalarValue<String>, SerializableArray {
|
||||
public:
|
||||
virtual ~PVString() {}
|
||||
...
|
||||
}
|
||||
class PVArray : public PVField, public SerializableArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVArray);
|
||||
virtual ~PVArray();
|
||||
std::size_t getLength() const;
|
||||
virtual void setLength(std::size_t length);
|
||||
std::size_t getCapacity() const;
|
||||
virtual void setCapacity(std::size_t capacity) = 0;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual void setImmutable();
|
||||
bool isCapacityMutable() const;
|
||||
void setCapacityMutable(bool isMutable);
|
||||
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class PVScalarArray : public PVArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVScalarArray);
|
||||
virtual ~PVScalarArray();
|
||||
typedef PVScalarArray &reference;
|
||||
typedef const PVScalarArray& const_reference;
|
||||
|
||||
const ScalarArrayConstPtr getScalarArray() const ;
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
virtual std::ostream& dumpValue(std::ostream& o, size_t index) const = 0;
|
||||
</font>
|
||||
...
|
||||
}
|
||||
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
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)
|
||||
{}
|
||||
};
|
||||
</font>
|
||||
|
||||
template<typename T>
|
||||
class PVValueArray : public PVScalarArray {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVValueArray);
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
// following are new typeDefs
|
||||
<font color = "blue">typedef shared_vector<T> svector;</font>
|
||||
<font color = "blue">typedef shared_vector<const T> const_svector; </font>
|
||||
|
||||
virtual ~PVValueArray() {}
|
||||
// following are added
|
||||
<font color = "blue">svector get();</font>
|
||||
<font color = "blue">void swap(svector& value);</font>
|
||||
<font color = "red">
|
||||
// following are removed
|
||||
typedef PVValueArray & reference;
|
||||
typedef const PVValueArray & const_reference;
|
||||
typedef PVArrayData<T> ArrayDataType;
|
||||
typedef std::vector<T> vector;
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
|
||||
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;
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
typedef PVValueArray<uint8> PVBooleanArray;
|
||||
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
|
||||
...
|
||||
typedef PVValueArray<String> PVStringArray;
|
||||
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
|
||||
|
||||
class PVStructure : public PVField,public BitSetSerializable {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVStructure);
|
||||
virtual ~PVStructure();
|
||||
typedef PVStructure & reference;
|
||||
typedef const PVStructure & const_reference;
|
||||
|
||||
StructureConstPtr getStructure() const;
|
||||
const PVFieldPtrArray & getPVFields() const;
|
||||
PVFieldPtr getSubField(String const &fieldName) const;
|
||||
PVFieldPtr getSubField(std::size_t fieldOffset) const;
|
||||
PVBooleanPtr getBooleanField(String const &fieldName) ;
|
||||
PVBytePtr getByteField(String const &fieldName) ;
|
||||
PVShortPtr getShortField(String const &fieldName) ;
|
||||
PVIntPtr getIntField(String const &fieldName) ;
|
||||
PVLongPtr getLongField(String const &fieldName) ;
|
||||
PVUBytePtr getUByteField(String const &fieldName) ;
|
||||
PVUShortPtr getUShortField(String const &fieldName) ;
|
||||
PVUIntPtr getUIntField(String const &fieldName) ;
|
||||
PVULongPtr getULongField(String const &fieldName) ;
|
||||
PVFloatPtr getFloatField(String const &fieldName) ;
|
||||
PVDoublePtr getDoubleField(String const &fieldName) ;
|
||||
PVStringPtr getStringField(String const &fieldName) ;
|
||||
PVStructurePtr getStructureField(String const &fieldName) ;
|
||||
PVScalarArrayPtr getScalarArrayField(
|
||||
String const &fieldName,ScalarType elementType) ;
|
||||
PVStructureArrayPtr getStructureArrayField(String const &fieldName) ;
|
||||
virtual void serialize(
|
||||
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
|
||||
virtual void deserialize(
|
||||
ByteBuffer *pbuffer,DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher,BitSet *pbitSet) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl*pflusher,BitSet *pbitSet);
|
||||
PVStructure(StructureConstPtr const & structure);
|
||||
PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields);
|
||||
<font color = "red">
|
||||
// following are removed
|
||||
void appendPVField(
|
||||
String const &fieldName,
|
||||
PVFieldPtr const & pvField);
|
||||
void appendPVFields(
|
||||
StringArray const & fieldNames,
|
||||
PVFieldPtrArray const & pvFields);
|
||||
void removePVField(String const &fieldName);
|
||||
virtual void setImmutable();
|
||||
String getExtendsStructureName() const;
|
||||
bool putExtendsStructureName(
|
||||
String const &extendsStructureName);
|
||||
</font>
|
||||
};
|
||||
|
||||
<font color = "red">
|
||||
// following will be removed
|
||||
typedef PVArrayData<PVStructurePtr> StructureArrayData;
|
||||
</font>
|
||||
|
||||
class PVStructureArray : public PVArray
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVStructureArray);
|
||||
typedef PVStructurePtr value_type;
|
||||
typedef PVStructurePtr* pointer;
|
||||
typedef const PVStructurePtr* const_pointer;
|
||||
<font color = "blue">
|
||||
// following are new typeDefs
|
||||
typedef shared_vector<PVStructurePtr> svector;
|
||||
typedef shared_vector<const PVStructurePtr> const_svector;
|
||||
</font>
|
||||
|
||||
virtual ~PVStructureArray() {}
|
||||
virtual void setCapacity(size_t capacity);
|
||||
virtual void setLength(std::size_t length);
|
||||
virtual StructureArrayConstPtr getStructureArray() const ;
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
|
||||
// following are new
|
||||
<font color = "blue"> svector get();</font>
|
||||
<font color = "blue"> void swap(svector & value);</font>
|
||||
<font color = "red">
|
||||
// following are removed
|
||||
typedef PVArrayData<PVStructurePtr> ArrayDataType;
|
||||
typedef std::vector<PVStructurePtr> vector;
|
||||
typedef const std::vector<PVStructurePtr> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVStructureArray &reference;
|
||||
typedef const PVStructureArray& const_reference;
|
||||
|
||||
virtual std::size_t append(std::size_t number);
|
||||
virtual bool remove(std::size_t offset,std::size_t number);
|
||||
virtual void compress();
|
||||
virtual std::size_t get(std::size_t offset, std::size_t length,
|
||||
StructureArrayData &data);
|
||||
virtual std::size_t put(std::size_t offset,std::size_t length,
|
||||
const_vector const & from, std::size_t fromOffset);
|
||||
virtual void shareData(
|
||||
shared_vector const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length);
|
||||
virtual pointer get() { return &((*value.get())[0]); }
|
||||
virtual pointer get() const { return &((*value.get())[0]); }
|
||||
virtual vector const & getVector() {return *value;}
|
||||
virtual shared_vector const & getSharedVector() {return value;}
|
||||
</font>
|
||||
...
|
||||
};
|
||||
|
||||
class PVDataCreate {
|
||||
public:
|
||||
static PVDataCreatePtr getPVDataCreate();
|
||||
PVFieldPtr createPVField(FieldConstPtr const & field);
|
||||
PVFieldPtr createPVField(PVFieldPtr const & fieldToClone);
|
||||
PVScalarPtr createPVScalar(ScalarConstPtr const & scalar);
|
||||
PVScalarPtr createPVScalar(ScalarType scalarType);
|
||||
PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone);
|
||||
PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
|
||||
PVScalarArrayPtr createPVScalarArray(ScalarType elementType);
|
||||
PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone);
|
||||
PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const & structureArray);
|
||||
PVStructurePtr createPVStructure(StructureConstPtr const & structure);
|
||||
PVStructurePtr createPVStructure(
|
||||
StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
|
||||
PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);
|
||||
...
|
||||
};
|
||||
|
||||
extern PVDataCreatePtr getPVDataCreate();
|
||||
</pre>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -24,6 +24,10 @@ INC += destroyable.h
|
||||
INC += status.h
|
||||
INC += sharedPtr.h
|
||||
INC += localStaticLock.h
|
||||
INC += typeCast.h
|
||||
INC += printer.h
|
||||
INC += sharedVector.h
|
||||
INC += templateMeta.h
|
||||
|
||||
LIBSRCS += byteBuffer.cpp
|
||||
LIBSRCS += bitSet.cpp
|
||||
@@ -37,6 +41,8 @@ LIBSRCS += timer.cpp
|
||||
LIBSRCS += status.cpp
|
||||
LIBSRCS += messageQueue.cpp
|
||||
LIBSRCS += localStaticLock.cpp
|
||||
LIBSRCS += typeCast.cpp
|
||||
LIBSRCS += parseToPOD.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/pv
|
||||
|
||||
@@ -64,6 +70,7 @@ LIBSRCS += Convert.cpp
|
||||
LIBSRCS += Compare.cpp
|
||||
LIBSRCS += StandardField.cpp
|
||||
LIBSRCS += StandardPVField.cpp
|
||||
LIBSRCS += printer.cpp
|
||||
|
||||
SRC_DIRS += $(PVDATA)/property
|
||||
|
||||
|
||||
@@ -15,13 +15,6 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
// PVXXX object comparison
|
||||
|
||||
bool operator==(PVField& left, PVField& right)
|
||||
{
|
||||
return getConvert()->equals(left,right);
|
||||
}
|
||||
|
||||
// Introspection object comparision
|
||||
|
||||
/** Field equality conditions:
|
||||
@@ -101,8 +94,142 @@ bool operator==(const StructureArray& a, const StructureArray& b)
|
||||
return *(a.getStructure().get())==*(b.getStructure().get());
|
||||
}
|
||||
|
||||
namespace nconvert {
|
||||
// PVXXX object comparison
|
||||
|
||||
} // namespace nconvert
|
||||
namespace {
|
||||
|
||||
// fully typed comparisons
|
||||
|
||||
template<typename T>
|
||||
bool compareScalar(const PVScalarValue<T>* left, const PVScalarValue<T>* right)
|
||||
{
|
||||
return left->get()==right->get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool compareArray(const PVValueArray<T>* left, const PVValueArray<T>* right)
|
||||
{
|
||||
typename PVValueArray<T>::const_svector lhs(left->view()), rhs(right->view());
|
||||
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||
}
|
||||
|
||||
// partially typed comparisons
|
||||
|
||||
bool compareField(const PVScalar* left, const PVScalar* right)
|
||||
{
|
||||
ScalarType lht = left->getScalar()->getScalarType();
|
||||
if(lht != right->getScalar()->getScalarType())
|
||||
return false;
|
||||
switch(lht) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return compareScalar(static_cast<const PVScalarValue<TYPE>*>(left), static_cast<const PVScalarValue<TYPE>*>(right))
|
||||
OP(pvBoolean, uint8);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
#undef OP
|
||||
case pvString: {
|
||||
const PVString *a=static_cast<const PVString*>(left), *b=static_cast<const PVString*>(right);
|
||||
return a->get()==b->get();
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVScalar with invalid scalar type!");
|
||||
}
|
||||
|
||||
bool compareField(const PVScalarArray* left, const PVScalarArray* right)
|
||||
{
|
||||
ScalarType lht = left->getScalarArray()->getElementType();
|
||||
if(lht != right->getScalarArray()->getElementType())
|
||||
return false;
|
||||
|
||||
if(left->getLength()!=right->getLength())
|
||||
return false;
|
||||
|
||||
switch(lht) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return compareArray(static_cast<const PVValueArray<TYPE>*>(left), static_cast<const PVValueArray<TYPE>*>(right))
|
||||
OP(pvBoolean, uint8);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
OP(pvString, String);
|
||||
#undef OP
|
||||
}
|
||||
throw std::logic_error("PVScalarArray with invalid element type!");
|
||||
}
|
||||
|
||||
bool compareField(const PVStructure* left, const PVStructure* right)
|
||||
{
|
||||
StructureConstPtr ls = left->getStructure();
|
||||
|
||||
if(*ls!=*right->getStructure())
|
||||
return false;
|
||||
|
||||
const PVFieldPtrArray& lf = left->getPVFields();
|
||||
const PVFieldPtrArray& rf = right->getPVFields();
|
||||
|
||||
for(size_t i=0, nfld=ls->getNumberFields(); i<nfld; i++) {
|
||||
if(*lf[i]!=*rf[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compareField(const PVStructureArray* left, const PVStructureArray* right)
|
||||
{
|
||||
if(*left->getStructureArray()->getStructure()
|
||||
!= *right->getStructureArray()->getStructure())
|
||||
return false;
|
||||
|
||||
PVStructureArray::const_svector ld=left->view(), rd=right->view();
|
||||
|
||||
if(ld.size()!=rd.size())
|
||||
return false;
|
||||
|
||||
PVStructureArray::const_svector::const_iterator lit, lend, rit;
|
||||
|
||||
for(lit=ld.begin(), lend=ld.end(), rit=rd.begin();
|
||||
lit!=lend;
|
||||
++lit, ++rit)
|
||||
{
|
||||
if(**lit != **rit)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
// untyped comparison
|
||||
|
||||
bool operator==(const PVField& left, const PVField& right)
|
||||
{
|
||||
if(&left == &right)
|
||||
return true;
|
||||
|
||||
Type lht = left.getField()->getType();
|
||||
if(lht != right.getField()->getType())
|
||||
return false;
|
||||
|
||||
switch(lht) {
|
||||
case scalar: return compareField(static_cast<const PVScalar*>(&left), static_cast<const PVScalar*>(&right));
|
||||
case scalarArray: return compareField(static_cast<const PVScalarArray*>(&left), static_cast<const PVScalarArray*>(&right));
|
||||
case structure: return compareField(static_cast<const PVStructure*>(&left), static_cast<const PVStructure*>(&right));
|
||||
case structureArray: return compareField(static_cast<const PVStructureArray*>(&left), static_cast<const PVStructureArray*>(&right));
|
||||
}
|
||||
throw std::logic_error("PVField with invalid type!");
|
||||
}
|
||||
|
||||
}} // namespace epics::pvData
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -66,7 +66,11 @@ struct StructureArrayHashFunction {
|
||||
|
||||
|
||||
Scalar::Scalar(ScalarType scalarType)
|
||||
: Field(scalar),scalarType(scalarType){}
|
||||
: Field(scalar),scalarType(scalarType)
|
||||
{
|
||||
if(scalarType<pvBoolean || scalarType>pvString)
|
||||
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType");
|
||||
}
|
||||
|
||||
Scalar::~Scalar(){}
|
||||
|
||||
@@ -166,7 +170,11 @@ static StructureConstPtr deserializeStructureField(const FieldCreate* fieldCreat
|
||||
}
|
||||
|
||||
ScalarArray::ScalarArray(ScalarType elementType)
|
||||
: Field(scalarArray),elementType(elementType){}
|
||||
: Field(scalarArray),elementType(elementType)
|
||||
{
|
||||
if(elementType<pvBoolean || elementType>pvString)
|
||||
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
|
||||
}
|
||||
|
||||
ScalarArray::~ScalarArray() {}
|
||||
|
||||
@@ -275,10 +283,12 @@ Structure::Structure (
|
||||
}
|
||||
size_t number = fields.size();
|
||||
for(size_t i=0; i<number; i++) {
|
||||
String name = fieldNames[i];
|
||||
if(name.size()<1) {
|
||||
const String& name = fieldNames[i];
|
||||
if(name.empty()) {
|
||||
throw std::invalid_argument("fieldNames has a zero length string");
|
||||
}
|
||||
if(fields[i].get()==NULL)
|
||||
throw std::invalid_argument("Can't construct Structure with NULL Field");
|
||||
// look for duplicates
|
||||
for(size_t j=i+1; j<number; j++) {
|
||||
String otherName = fieldNames[j];
|
||||
|
||||
@@ -19,83 +19,32 @@ using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PVArrayPvt {
|
||||
public:
|
||||
PVArrayPvt() : length(0),capacity(0),capacityMutable(true)
|
||||
{}
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
bool capacityMutable;
|
||||
};
|
||||
|
||||
PVArray::PVArray(FieldConstPtr const & field)
|
||||
: PVField(field),pImpl(new PVArrayPvt())
|
||||
: PVField(field),capacityMutable(true)
|
||||
{ }
|
||||
|
||||
PVArray::~PVArray()
|
||||
{
|
||||
delete pImpl;
|
||||
}
|
||||
|
||||
void PVArray::setImmutable()
|
||||
{
|
||||
pImpl->capacityMutable = false;
|
||||
capacityMutable = false;
|
||||
PVField::setImmutable();
|
||||
}
|
||||
|
||||
size_t PVArray::getLength() const {return pImpl->length;}
|
||||
|
||||
size_t PVArray::getCapacity() const {return pImpl->capacity;}
|
||||
|
||||
static String fieldImmutable("field is immutable");
|
||||
|
||||
void PVArray::setLength(size_t length) {
|
||||
if(length==pImpl->length) return;
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
if(length>pImpl->capacity) this->setCapacity(length);
|
||||
if(length>pImpl->capacity) length = pImpl->capacity;
|
||||
pImpl->length = length;
|
||||
}
|
||||
|
||||
void PVArray::setCapacityLength(size_t capacity,size_t length) {
|
||||
pImpl->capacity = capacity;
|
||||
pImpl->length = length;
|
||||
}
|
||||
|
||||
|
||||
bool PVArray::isCapacityMutable() const
|
||||
{
|
||||
if(PVField::isImmutable()) {
|
||||
return false;
|
||||
}
|
||||
return pImpl->capacityMutable;
|
||||
return capacityMutable;
|
||||
}
|
||||
|
||||
void PVArray::setCapacityMutable(bool isMutable)
|
||||
{
|
||||
if(isMutable && PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
throw std::runtime_error("field is immutable");
|
||||
}
|
||||
pImpl->capacityMutable = isMutable;
|
||||
capacityMutable = isMutable;
|
||||
}
|
||||
|
||||
static String capacityImmutable("capacity is immutable");
|
||||
|
||||
void PVArray::setCapacity(size_t capacity) {
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message(fieldImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
if(pImpl->capacityMutable==false) {
|
||||
PVField::message(capacityImmutable,errorMessage);
|
||||
return;
|
||||
}
|
||||
pImpl->capacity = capacity;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,32 @@ using std::min;
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
|
||||
template<> const ScalarType PVBoolean::typeCode = pvBoolean;
|
||||
template<> const ScalarType PVByte::typeCode = pvByte;
|
||||
template<> const ScalarType PVShort::typeCode = pvShort;
|
||||
template<> const ScalarType PVInt::typeCode = pvInt;
|
||||
template<> const ScalarType PVLong::typeCode = pvLong;
|
||||
template<> const ScalarType PVUByte::typeCode = pvUByte;
|
||||
template<> const ScalarType PVUShort::typeCode = pvUShort;
|
||||
template<> const ScalarType PVUInt::typeCode = pvUInt;
|
||||
template<> const ScalarType PVULong::typeCode = pvULong;
|
||||
template<> const ScalarType PVFloat::typeCode = pvFloat;
|
||||
template<> const ScalarType PVDouble::typeCode = pvDouble;
|
||||
template<> const ScalarType PVScalarValue<String>::typeCode = pvString;
|
||||
|
||||
template<> const ScalarType PVBooleanArray::typeCode = pvBoolean;
|
||||
template<> const ScalarType PVByteArray::typeCode = pvByte;
|
||||
template<> const ScalarType PVShortArray::typeCode = pvShort;
|
||||
template<> const ScalarType PVIntArray::typeCode = pvInt;
|
||||
template<> const ScalarType PVLongArray::typeCode = pvLong;
|
||||
template<> const ScalarType PVUByteArray::typeCode = pvUByte;
|
||||
template<> const ScalarType PVUShortArray::typeCode = pvUShort;
|
||||
template<> const ScalarType PVUIntArray::typeCode = pvUInt;
|
||||
template<> const ScalarType PVULongArray::typeCode = pvULong;
|
||||
template<> const ScalarType PVFloatArray::typeCode = pvFloat;
|
||||
template<> const ScalarType PVDoubleArray::typeCode = pvDouble;
|
||||
template<> const ScalarType PVStringArray::typeCode = pvString;
|
||||
|
||||
/** Default storage for scalar values
|
||||
*/
|
||||
template<typename T>
|
||||
@@ -170,157 +196,79 @@ public:
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
|
||||
typedef ::epics::pvData::shared_vector<T> svector;
|
||||
typedef ::epics::pvData::shared_vector<const T> const_svector;
|
||||
|
||||
DefaultPVArray(ScalarArrayConstPtr const & scalarArray);
|
||||
virtual ~DefaultPVArray();
|
||||
|
||||
virtual size_t getLength() const {return value.size();}
|
||||
virtual size_t getCapacity() const {return value.capacity();}
|
||||
|
||||
virtual void setCapacity(size_t capacity);
|
||||
virtual void setLength(size_t length);
|
||||
virtual size_t get(size_t offset, size_t length, PVArrayData<T> &data) ;
|
||||
virtual size_t put(size_t offset,size_t length, const_pointer from,
|
||||
size_t fromOffset);
|
||||
virtual void shareData(
|
||||
std::tr1::shared_ptr<std::vector<T> > const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length);
|
||||
virtual pointer get() ;
|
||||
virtual pointer get() const ;
|
||||
virtual vector const & getVector() { return *value.get(); }
|
||||
virtual shared_vector const & getSharedVector(){return value;};
|
||||
|
||||
virtual const_svector view() const {return value;}
|
||||
virtual void swap(const_svector &other);
|
||||
virtual void replace(const const_svector& next);
|
||||
|
||||
// from Serializable
|
||||
virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const;
|
||||
private:
|
||||
shared_vector value;
|
||||
const_svector value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
T *DefaultPVArray<T>::get()
|
||||
{
|
||||
std::vector<T> *vec = value.get();
|
||||
T *praw = &((*vec)[0]);
|
||||
return praw;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T *DefaultPVArray<T>::get() const
|
||||
{
|
||||
std::vector<T> *vec = value.get();
|
||||
T *praw = &((*vec)[0]);
|
||||
return praw;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
DefaultPVArray<T>::DefaultPVArray(ScalarArrayConstPtr const & scalarArray)
|
||||
: PVValueArray<T>(scalarArray),
|
||||
value(std::tr1::shared_ptr<std::vector<T> >(new std::vector<T>()))
|
||||
value()
|
||||
|
||||
{ }
|
||||
|
||||
template<typename T>
|
||||
DefaultPVArray<T>::~DefaultPVArray()
|
||||
{ }
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::setCapacity(size_t capacity)
|
||||
{
|
||||
if(PVArray::getCapacity()==capacity) return;
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
if(this->isCapacityMutable()) {
|
||||
value.reserve(capacity);
|
||||
}
|
||||
size_t length = PVArray::getLength();
|
||||
if(length>capacity) length = capacity;
|
||||
size_t oldCapacity = PVArray::getCapacity();
|
||||
if(oldCapacity>capacity) {
|
||||
std::vector<T> array;
|
||||
array.reserve(capacity);
|
||||
array.resize(length);
|
||||
T * from = get();
|
||||
for (size_t i=0; i<length; i++) array[i] = from[i];
|
||||
value->swap(array);
|
||||
} else {
|
||||
value->reserve(capacity);
|
||||
}
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::setLength(size_t length)
|
||||
{
|
||||
if(PVArray::getLength()==length) return;
|
||||
size_t capacity = PVArray::getCapacity();
|
||||
if(length>capacity) {
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
setCapacity(length);
|
||||
}
|
||||
value->resize(length);
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
if(length == value.size())
|
||||
return;
|
||||
else if(length < value.size())
|
||||
value.slice(0, length);
|
||||
else
|
||||
value.resize(length);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
size_t DefaultPVArray<T>::get(size_t offset, size_t len, PVArrayData<T> &data)
|
||||
void DefaultPVArray<T>::replace(const const_svector& next)
|
||||
{
|
||||
size_t n = len;
|
||||
size_t length = this->getLength();
|
||||
if(offset+len > length) {
|
||||
n = length-offset;
|
||||
//if(n<0) n = 0;
|
||||
}
|
||||
data.data = *value.get();
|
||||
data.offset = offset;
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
size_t DefaultPVArray<T>::put(size_t offset,size_t len,
|
||||
const_pointer from,size_t fromOffset)
|
||||
{
|
||||
if(PVField::isImmutable()) {
|
||||
PVField::message("field is immutable",errorMessage);
|
||||
return 0;
|
||||
}
|
||||
T * pvalue = get();
|
||||
if(from==pvalue) return len;
|
||||
if(len<1) return 0;
|
||||
size_t length = this->getLength();
|
||||
size_t capacity = this->getCapacity();
|
||||
if(offset+len > length) {
|
||||
size_t newlength = offset + len;
|
||||
if(newlength>capacity) {
|
||||
setCapacity(newlength);
|
||||
newlength = this->getCapacity();
|
||||
len = newlength - offset;
|
||||
if(len<=0) return 0;
|
||||
}
|
||||
length = newlength;
|
||||
setLength(length);
|
||||
}
|
||||
pvalue = get();
|
||||
for(size_t i=0;i<len;i++) {
|
||||
pvalue[i+offset] = from[i+fromOffset];
|
||||
}
|
||||
this->setLength(length);
|
||||
value = next;
|
||||
this->postPut();
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::shareData(
|
||||
std::tr1::shared_ptr<std::vector<T> > const & sharedValue,
|
||||
std::size_t capacity,
|
||||
std::size_t length)
|
||||
void DefaultPVArray<T>::swap(const_svector &other)
|
||||
{
|
||||
value = sharedValue;
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
@@ -331,93 +279,92 @@ template<typename T>
|
||||
void DefaultPVArray<T>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
// alignment if (size>0) { pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T)); }
|
||||
//if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>this->getCapacity()) this->setCapacity(size);
|
||||
// set new length
|
||||
this->setLength(size);
|
||||
|
||||
// try to avoid deserializing from the buffer
|
||||
// this is only possible if we do not need to do endian-swapping
|
||||
if (!pbuffer->reverse<T>())
|
||||
if (pcontrol->directDeserialize(pbuffer, (char*)(get()), size, sizeof(T)))
|
||||
{
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
return;
|
||||
}
|
||||
svector nextvalue(thaw(value));
|
||||
nextvalue.resize(size); // TODO: avoid copy of stuff we will then overwrite
|
||||
|
||||
// retrieve value from the buffer
|
||||
size_t i = 0;
|
||||
T * pvalue = get();
|
||||
while(true) {
|
||||
/*
|
||||
size_t maxIndex = min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
value[i] = pbuffer->get<T>();
|
||||
*/
|
||||
size_t maxCount = min(size-i, (pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->getArray(pvalue+i, maxCount);
|
||||
i += maxCount;
|
||||
|
||||
if(i<size)
|
||||
pcontrol->ensureData(sizeof(T)); // this is not OK since can exceen max local buffer (size-i)*sizeof(T));
|
||||
else
|
||||
break;
|
||||
}
|
||||
T* cur = nextvalue.data();
|
||||
|
||||
// try to avoid deserializing from the buffer
|
||||
// this is only possible if we do not need to do endian-swapping
|
||||
if (!pbuffer->reverse<T>())
|
||||
if (pcontrol->directDeserialize(pbuffer, (char*)cur, size, sizeof(T)))
|
||||
{
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
//}
|
||||
// TODO null arrays (size == -1) not supported
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve value from the buffer
|
||||
size_t remaining = size;
|
||||
while(remaining) {
|
||||
const size_t have_bytes = pbuffer->getRemaining();
|
||||
|
||||
// correctly rounds down in an element is partially received
|
||||
const size_t available = have_bytes/sizeof(T);
|
||||
|
||||
if(available == 0) {
|
||||
size_t want = sizeof(T);
|
||||
if(remaining==1 && sizeof(T)>1) {
|
||||
// Need to wait for the last few bytes
|
||||
// of the final element.
|
||||
// available==0 implies have_bytes<sizeof(T)
|
||||
want = sizeof(T) - have_bytes;
|
||||
}
|
||||
// recv() at least one element, or remaining buffer
|
||||
pcontrol->ensureData(want);
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t n2read = std::min(remaining, available);
|
||||
|
||||
pbuffer->getArray(cur, n2read);
|
||||
cur += n2read;
|
||||
remaining -= n2read;
|
||||
}
|
||||
value = freeze(nextvalue);
|
||||
// inform about the change?
|
||||
PVField::postPut();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DefaultPVArray<T>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
// cache
|
||||
size_t length = this->getLength();
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const
|
||||
{
|
||||
//TODO: avoid incrementing the ref counter...
|
||||
const_svector temp(value);
|
||||
temp.slice(offset, count);
|
||||
count = temp.size();
|
||||
|
||||
// check bounds
|
||||
/*if(offset<0)
|
||||
offset = 0;
|
||||
else*/ if(offset>length) offset = length;
|
||||
//if(count<0) count = length;
|
||||
|
||||
size_t maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
//if (count == 0) return; pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T));
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
const T* cur = temp.data();
|
||||
|
||||
// try to avoid copying into the buffer
|
||||
// this is only possible if we do not need to do endian-swapping
|
||||
if (!pbuffer->reverse<T>())
|
||||
if (pflusher->directSerialize(pbuffer, (const char*)(get()+offset), count, sizeof(T)))
|
||||
if (pflusher->directSerialize(pbuffer, (const char*)cur, count, sizeof(T)))
|
||||
return;
|
||||
|
||||
size_t end = offset+count;
|
||||
size_t i = offset;
|
||||
T * pvalue = const_cast<T *>(get());
|
||||
while(true) {
|
||||
|
||||
/*
|
||||
size_t maxIndex = min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i;
|
||||
for(; i<maxIndex; i++)
|
||||
pbuffer->put<T>(value[i]);
|
||||
*/
|
||||
|
||||
size_t maxCount = min<int>(end-i, (int)(pbuffer->getRemaining()/sizeof(T)));
|
||||
pbuffer->putArray(pvalue+i, maxCount);
|
||||
i += maxCount;
|
||||
|
||||
if(i<end)
|
||||
while(count) {
|
||||
const size_t empty = pbuffer->getRemaining();
|
||||
const size_t space_for = empty/sizeof(T);
|
||||
|
||||
if(space_for==0) {
|
||||
pflusher->flushSerializeBuffer();
|
||||
else
|
||||
break;
|
||||
// Can we be certain that more space is now free???
|
||||
// If not then we spinnnnnnnnn
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t n2send = std::min(count, space_for);
|
||||
|
||||
pbuffer->putArray(cur, n2send);
|
||||
cur += n2send;
|
||||
count -= n2send;
|
||||
}
|
||||
|
||||
pflusher->flushSerializeBuffer();
|
||||
}
|
||||
|
||||
// specializations for String
|
||||
@@ -426,42 +373,37 @@ template<>
|
||||
void DefaultPVArray<String>::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
//if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>getCapacity()) setCapacity(size);
|
||||
// set new length
|
||||
setLength(size);
|
||||
// retrieve value from the buffer
|
||||
String * pvalue = get();
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pvalue[i] = SerializeHelper::deserializeString(pbuffer,
|
||||
pcontrol);
|
||||
}
|
||||
// inform about the change?
|
||||
postPut();
|
||||
//}
|
||||
// TODO null arrays (size == -1) not supported
|
||||
|
||||
svector nextvalue(thaw(value));
|
||||
|
||||
// Decide if we must re-allocate
|
||||
if(size > nextvalue.size() || !nextvalue.unique())
|
||||
nextvalue.resize(size);
|
||||
else if(size < nextvalue.size())
|
||||
nextvalue.slice(0, size);
|
||||
|
||||
|
||||
String * pvalue = nextvalue.data();
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pvalue[i] = SerializeHelper::deserializeString(pbuffer,
|
||||
pcontrol);
|
||||
}
|
||||
value = freeze(nextvalue);
|
||||
// inform about the change?
|
||||
postPut();
|
||||
}
|
||||
|
||||
template<>
|
||||
void DefaultPVArray<String>::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
size_t length = getLength();
|
||||
|
||||
// check bounds
|
||||
/*if(offset<0)
|
||||
offset = 0;
|
||||
else*/ if(offset>length) offset = length;
|
||||
//if(count<0) count = length;
|
||||
const_svector temp(value);
|
||||
temp.slice(offset, count);
|
||||
|
||||
size_t maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
size_t end = offset+count;
|
||||
String * pvalue = get();
|
||||
for(size_t i = offset; i<end; i++) {
|
||||
const String * pvalue = temp.data();
|
||||
for(size_t i = 0; i<temp.size(); i++) {
|
||||
SerializeHelper::serializeString(pvalue[i], pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
@@ -646,7 +588,7 @@ PVScalarArrayPtr PVDataCreate::createPVScalarArray(
|
||||
{
|
||||
PVScalarArrayPtr pvArray = createPVScalarArray(
|
||||
arrayToClone->getScalarArray()->getElementType());
|
||||
getConvert()->copyScalarArray(arrayToClone,0, pvArray,0,arrayToClone->getLength());
|
||||
pvArray->assign(*arrayToClone.get());
|
||||
PVAuxInfoPtr from = arrayToClone->getPVAuxInfo();
|
||||
PVAuxInfoPtr to = pvArray->getPVAuxInfo();
|
||||
PVAuxInfo::PVInfoMap & map = from->getInfoMap();
|
||||
|
||||
@@ -26,8 +26,7 @@ PVField::PVField(FieldConstPtr field)
|
||||
: notImplemented("not implemented"),
|
||||
parent(NULL),field(field),
|
||||
fieldOffset(0), nextFieldOffset(0),
|
||||
immutable(false),
|
||||
convert(getConvert())
|
||||
immutable(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -64,11 +63,6 @@ void PVField::message(String message,MessageType messageType)
|
||||
PVField::message(message,messageType,"");
|
||||
}
|
||||
|
||||
String PVField::getFieldName() const
|
||||
{
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
void PVField::setRequester(RequesterPtr const &req)
|
||||
{
|
||||
if(parent!=NULL) {
|
||||
@@ -180,7 +174,7 @@ void PVField::setParentAndName(PVStructure * xxx,String const & name)
|
||||
|
||||
bool PVField::equals(PVField &pv)
|
||||
{
|
||||
return convert->equals(*this,pv);
|
||||
return pv==*this;
|
||||
}
|
||||
|
||||
void PVField::toString(StringBuilder buf)
|
||||
@@ -190,7 +184,7 @@ void PVField::toString(StringBuilder buf)
|
||||
|
||||
void PVField::toString(StringBuilder buf,int indentLevel)
|
||||
{
|
||||
convert->getString(buf,this,indentLevel);
|
||||
Convert().getString(buf,this,indentLevel);
|
||||
if(pvAuxInfo.get()!=NULL) pvAuxInfo->toString(buf,indentLevel);
|
||||
}
|
||||
|
||||
@@ -223,6 +217,31 @@ namespace format
|
||||
}
|
||||
};
|
||||
|
||||
String PVField::getFullName() const
|
||||
{
|
||||
size_t size=fieldName.size();
|
||||
|
||||
for(PVField *fld=getParent(); fld; fld=fld->getParent())
|
||||
{
|
||||
size+=fld->fieldName.size()+1;
|
||||
}
|
||||
|
||||
String ret(size, '.');
|
||||
size_t pos=size - fieldName.size();
|
||||
|
||||
ret.replace(pos, String::npos, fieldName);
|
||||
|
||||
for(PVField *fld=getParent(); fld; fld=fld->getParent())
|
||||
{
|
||||
const String& nref = fld->fieldName;
|
||||
assert(pos >= nref.size()+1);
|
||||
pos -= nref.size()+1;
|
||||
ret.replace(pos, String::npos, nref);
|
||||
}
|
||||
assert(pos==0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PVField::computeOffset(const PVField * pvField) {
|
||||
const PVStructure * pvTop = pvField->getParent();
|
||||
if(pvTop==NULL) {
|
||||
|
||||
@@ -28,16 +28,4 @@ namespace epics { namespace pvData {
|
||||
return static_pointer_cast<const ScalarArray>(PVField::getField());
|
||||
}
|
||||
|
||||
template<>
|
||||
std::ostream& PVValueArray<int8>::dumpValue(std::ostream& o, size_t index) const
|
||||
{
|
||||
return o << static_cast<int>(*(get() + index));
|
||||
}
|
||||
|
||||
template<>
|
||||
std::ostream& PVValueArray<uint8>::dumpValue(std::ostream& o, size_t index) const
|
||||
{
|
||||
return o << static_cast<unsigned int>(*(get() + index));
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -21,44 +21,52 @@ using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PVStructureArray::PVStructureArray(StructureArrayConstPtr const & structureArray)
|
||||
: PVArray(structureArray),
|
||||
structureArray(structureArray),
|
||||
value(std::tr1::shared_ptr<PVStructurePtrArray>(new PVStructurePtrArray()))
|
||||
{
|
||||
}
|
||||
|
||||
size_t PVStructureArray::append(size_t number)
|
||||
{
|
||||
size_t currentLength = getLength();
|
||||
size_t newLength = currentLength + number;
|
||||
setCapacity(newLength);
|
||||
setLength(newLength);
|
||||
svector data(reuse());
|
||||
data.resize(data.size()+number);
|
||||
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
PVStructurePtrArray *to = value.get();
|
||||
for(size_t i=currentLength; i<newLength; i++) {
|
||||
(*to)[i] =getPVDataCreate()->createPVStructure(structure);
|
||||
}
|
||||
|
||||
for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number)
|
||||
*it = getPVDataCreate()->createPVStructure(structure);
|
||||
|
||||
size_t newLength = data.size();
|
||||
|
||||
const_svector cdata(freeze(data));
|
||||
swap(cdata);
|
||||
|
||||
return newLength;
|
||||
}
|
||||
|
||||
bool PVStructureArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
size_t length = getLength();
|
||||
if(offset+number>length) return false;
|
||||
PVStructurePtrArray vec = *value.get();
|
||||
if(number==0)
|
||||
return true;
|
||||
else if(offset+number>getLength())
|
||||
return false;
|
||||
|
||||
svector vec(reuse());
|
||||
|
||||
size_t length = vec.size();
|
||||
|
||||
for(size_t i = offset; i+number < length; i++) {
|
||||
vec[i] = vec[i + number];
|
||||
vec[i].swap(vec[i + number]);
|
||||
}
|
||||
size_t newLength = length - number;
|
||||
setCapacityLength(newLength,newLength);
|
||||
|
||||
vec.resize(length - number);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVStructureArray::compress() {
|
||||
size_t length = getCapacity();
|
||||
svector vec(reuse()); // TODO: check for first NULL before realloc
|
||||
|
||||
size_t length = vec.size();
|
||||
size_t newLength = 0;
|
||||
PVStructurePtrArray vec = *value.get();
|
||||
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(vec[i].get()!=NULL) {
|
||||
newLength++;
|
||||
@@ -80,113 +88,50 @@ void PVStructureArray::compress() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
setCapacityLength(newLength,newLength);
|
||||
|
||||
vec.resize(newLength);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
}
|
||||
|
||||
void PVStructureArray::setCapacity(size_t capacity) {
|
||||
if(getCapacity()==capacity) return;
|
||||
if(!isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
void PVStructureArray::setCapacity(size_t capacity)
|
||||
{
|
||||
if(this->isCapacityMutable()) {
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(value.capacity()<capacity) {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.reserve(capacity);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
size_t length = getLength();
|
||||
if(length>capacity) length = capacity;
|
||||
size_t oldCapacity = getCapacity();
|
||||
if(oldCapacity>capacity) {
|
||||
PVStructurePtrArray array;
|
||||
array.reserve(capacity);
|
||||
array.resize(length);
|
||||
PVStructurePtr * from = get();
|
||||
for (size_t i=0; i<length; i++) array[i] = from[i];
|
||||
value->swap(array);
|
||||
}
|
||||
|
||||
void PVStructureArray::setLength(size_t length)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(length == value.size()) {
|
||||
// nothing
|
||||
} else if(length < value.size()) {
|
||||
value.slice(0, length);
|
||||
} else {
|
||||
value->reserve(capacity);
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.resize(length);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
setCapacityLength(capacity,length);
|
||||
swap(value);
|
||||
}
|
||||
|
||||
void PVStructureArray::setLength(size_t length) {
|
||||
if(PVArray::getLength()==length) return;
|
||||
size_t capacity = PVArray::getCapacity();
|
||||
if(length>capacity) {
|
||||
if(!PVArray::isCapacityMutable()) {
|
||||
std::string message("not capacityMutable");
|
||||
PVField::message(message, errorMessage);
|
||||
return;
|
||||
}
|
||||
setCapacity(length);
|
||||
}
|
||||
value->resize(length);
|
||||
PVArray::setCapacityLength(capacity,length);
|
||||
}
|
||||
|
||||
StructureArrayConstPtr PVStructureArray::getStructureArray() const
|
||||
void PVStructureArray::swap(const_svector &other)
|
||||
{
|
||||
return structureArray;
|
||||
}
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
|
||||
size_t PVStructureArray::get(
|
||||
size_t offset, size_t len, StructureArrayData &data)
|
||||
{
|
||||
size_t n = len;
|
||||
size_t length = getLength();
|
||||
if(offset+len > length) {
|
||||
n = length - offset;
|
||||
//if(n<0) n = 0;
|
||||
}
|
||||
data.data = *value.get();
|
||||
data.offset = offset;
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t PVStructureArray::put(size_t offset,size_t len,
|
||||
const_vector const & from, size_t fromOffset)
|
||||
{
|
||||
if(isImmutable()) {
|
||||
message(String("field is immutable"), errorMessage);
|
||||
return 0;
|
||||
}
|
||||
if(&from==value.get()) return 0;
|
||||
if(len<1) return 0;
|
||||
size_t length = getLength();
|
||||
size_t capacity = getCapacity();
|
||||
if(offset+len > length) {
|
||||
size_t newlength = offset + len;
|
||||
if(newlength>capacity) {
|
||||
setCapacity(newlength);
|
||||
capacity = getCapacity();
|
||||
newlength = capacity;
|
||||
len = newlength - offset;
|
||||
if(len<=0) return 0;
|
||||
}
|
||||
length = newlength;
|
||||
setLength(length);
|
||||
}
|
||||
PVStructurePtrArray *to = value.get();
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
for(size_t i=0; i<len; i++) {
|
||||
PVStructurePtr frompv = from[i+fromOffset];
|
||||
if(frompv.get()!=NULL) {
|
||||
if(frompv->getStructure()!=structure) {
|
||||
throw std::invalid_argument(String(
|
||||
"Element is not a compatible structure"));
|
||||
}
|
||||
}
|
||||
(*to)[i+offset] = frompv;
|
||||
}
|
||||
postPut();
|
||||
setLength(length);
|
||||
return len;
|
||||
}
|
||||
|
||||
void PVStructureArray::shareData(
|
||||
std::tr1::shared_ptr<std::vector<PVStructurePtr> > const & sharedValue,
|
||||
std::size_t capacity,
|
||||
std::size_t length)
|
||||
{
|
||||
value = sharedValue;
|
||||
setCapacityLength(capacity,length);
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
@@ -196,56 +141,47 @@ void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
|
||||
void PVStructureArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
//if(size>=0) {
|
||||
// prepare array, if necessary
|
||||
if(size>getCapacity()) setCapacity(size);
|
||||
setLength(size);
|
||||
PVStructurePtrArray *pvArray = value.get();
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
size_t temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
(*pvArray)[i].reset();
|
||||
}
|
||||
else {
|
||||
if((*pvArray)[i].get()==NULL) {
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
(*pvArray)[i] = getPVDataCreate()->createPVStructure(structure);
|
||||
}
|
||||
(*pvArray)[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
data.resize(size);
|
||||
|
||||
StructureConstPtr structure = structureArray->getStructure();
|
||||
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
size_t temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
data[i].reset();
|
||||
}
|
||||
postPut();
|
||||
//}
|
||||
else {
|
||||
if(data[i].get()==NULL) {
|
||||
data[i] = getPVDataCreate()->createPVStructure(structure);
|
||||
}
|
||||
data[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
}
|
||||
replace(freeze(data)); // calls postPut()
|
||||
}
|
||||
|
||||
void PVStructureArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
// cache
|
||||
size_t length = getLength();
|
||||
|
||||
// check bounds
|
||||
/*if(offset<0)
|
||||
offset = 0;
|
||||
else*/ if(offset>length) offset = length;
|
||||
//if(count<0) count = length;
|
||||
const_svector temp(view());
|
||||
temp.slice(offset, count);
|
||||
|
||||
size_t maxCount = length-offset;
|
||||
if(count>maxCount) count = maxCount;
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
PVStructurePtrArray pvArray = *value.get();
|
||||
// write
|
||||
SerializeHelper::writeSize(count, pbuffer, pflusher);
|
||||
for(size_t i = 0; i<count; i++) {
|
||||
if(pbuffer->getRemaining()<1) pflusher->flushSerializeBuffer();
|
||||
PVStructurePtr pvStructure = pvArray[i+offset];
|
||||
if(pvStructure.get()==NULL) {
|
||||
if(pbuffer->getRemaining()<1)
|
||||
pflusher->flushSerializeBuffer();
|
||||
|
||||
if(temp[i].get()==NULL) {
|
||||
pbuffer->putByte(0);
|
||||
}
|
||||
else {
|
||||
pbuffer->putByte(1);
|
||||
pvStructure->serialize(pbuffer, pflusher);
|
||||
temp[i]->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,9 +203,9 @@ std::ostream& PVStructureArray::dumpValue(std::ostream& o) const
|
||||
|
||||
std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
PVStructurePtrArray pvArray = *value.get();
|
||||
PVStructurePtr pvStructure = pvArray[index];
|
||||
return o << *(pvStructure.get());
|
||||
const_svector temp(view());
|
||||
if(index<temp.size())
|
||||
o << temp[index].get();
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,11 +59,9 @@ PVStructurePtr StandardPVField::enumerated(StringArray const &choices)
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"choices",pvString);
|
||||
if(pvScalarArray.get()==NULL) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray * pvChoices = static_cast<PVStringArray *>(pvScalarArray.get());
|
||||
pvChoices->put(0,choices.size(),get(choices),0);
|
||||
PVStringArray::svector cdata(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), cdata.begin());
|
||||
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
@@ -74,11 +72,9 @@ PVStructurePtr StandardPVField::enumerated(
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(field);
|
||||
PVScalarArrayPtr pvScalarArray = pvStructure->getScalarArrayField(
|
||||
"value.choices",pvString);
|
||||
if(pvScalarArray.get()==NULL) {
|
||||
throw std::logic_error(String("StandardPVField::enumerated"));
|
||||
}
|
||||
PVStringArray * pvChoices = static_cast<PVStringArray *>(pvScalarArray.get());
|
||||
pvChoices->put(0,choices.size(),get(choices),0);
|
||||
PVStringArray::svector cdata(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), cdata.begin());
|
||||
static_cast<PVStringArray&>(*pvScalarArray).replace(freeze(cdata));
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/epicsException.h>
|
||||
#include <pv/sharedVector.h>
|
||||
|
||||
#include "dbDefs.h" // for NELEMENTS
|
||||
|
||||
@@ -61,7 +62,7 @@ namespace ScalarTypeFunc {
|
||||
"ubyte", "ushort", "uint", "ulong",
|
||||
"float", "double", "string",
|
||||
};
|
||||
ScalarType getScalarType(String pvalue) {
|
||||
ScalarType getScalarType(const String& pvalue) {
|
||||
for(size_t i=0; i<NELEMENTS(names); i++)
|
||||
if(pvalue==names[i])
|
||||
return ScalarType(i);
|
||||
@@ -78,6 +79,50 @@ namespace ScalarTypeFunc {
|
||||
*buf += name(scalarType);
|
||||
}
|
||||
|
||||
size_t elementSize(ScalarType id)
|
||||
{
|
||||
switch(id) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return sizeof(TYPE)
|
||||
OP(pvBoolean, boolean);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
OP(pvString, String);
|
||||
#undef OP
|
||||
default:
|
||||
THROW_EXCEPTION2(std::invalid_argument, "error unknown ScalarType");
|
||||
}
|
||||
}
|
||||
|
||||
shared_vector<void> allocArray(ScalarType id, size_t len)
|
||||
{
|
||||
switch(id) {
|
||||
#define OP(ENUM, TYPE) case ENUM: return static_shared_vector_cast<void>(shared_vector<TYPE>(len))
|
||||
OP(pvBoolean, boolean);
|
||||
OP(pvUByte, uint8);
|
||||
OP(pvByte, int8);
|
||||
OP(pvUShort, uint16);
|
||||
OP(pvShort, int16);
|
||||
OP(pvUInt, uint32);
|
||||
OP(pvInt, int32);
|
||||
OP(pvULong, uint64);
|
||||
OP(pvLong, int64);
|
||||
OP(pvFloat, float);
|
||||
OP(pvDouble, double);
|
||||
OP(pvString, String);
|
||||
#undef OP
|
||||
default:
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ScalarTypeFunc
|
||||
|
||||
}}
|
||||
|
||||
201
pvDataApp/factory/printer.cpp
Normal file
201
pvDataApp/factory/printer.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "pv/printer.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void indentN(std::ostream& strm, size_t N)
|
||||
{
|
||||
while(N--)
|
||||
strm.put(' ');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
PrinterBase::PrinterBase()
|
||||
:strm(NULL)
|
||||
{}
|
||||
|
||||
PrinterBase::~PrinterBase() {}
|
||||
|
||||
void PrinterBase::setStream(std::ostream& s)
|
||||
{
|
||||
strm = &s;
|
||||
}
|
||||
|
||||
void PrinterBase::clearStream()
|
||||
{
|
||||
strm = NULL;
|
||||
}
|
||||
|
||||
void PrinterBase::print(const PVField& pv)
|
||||
{
|
||||
if(!strm)
|
||||
throw std::runtime_error("No stream set for PV Printer");
|
||||
impl_print(pv);
|
||||
}
|
||||
|
||||
void PrinterBase::beginStructure(const PVStructure&) {}
|
||||
void PrinterBase::endStructure(const PVStructure&) {}
|
||||
|
||||
void PrinterBase::beginStructureArray(const PVStructureArray&) {}
|
||||
void PrinterBase::endStructureArray(const PVStructureArray&) {}
|
||||
|
||||
void PrinterBase::encodeScalar(const PVScalar& pv) {}
|
||||
|
||||
void PrinterBase::encodeArray(const PVScalarArray&) {}
|
||||
|
||||
void PrinterBase::encodeNull() {}
|
||||
|
||||
void PrinterBase::impl_print(const PVField& pv)
|
||||
{
|
||||
static const PVField* marker = (const PVField*)▮
|
||||
|
||||
/* Depth first recursive iteration.
|
||||
* Each PV to be printed is appended to the todo queue.
|
||||
* The last child of a structure is followed by a NULL.
|
||||
* As the tree is walked structures and structarrays
|
||||
* are appended to the inprog queue.
|
||||
*/
|
||||
std::deque<const PVField*> todo, inprog;
|
||||
|
||||
todo.push_back(&pv);
|
||||
|
||||
while(!todo.empty()) {
|
||||
const PVField *next = todo.front();
|
||||
todo.pop_front();
|
||||
|
||||
if(next==marker) {
|
||||
// finished with a structure or structarray,
|
||||
// now we fall back to its parent.
|
||||
assert(!inprog.empty());
|
||||
switch(inprog.back()->getField()->getType()) {
|
||||
case structure:
|
||||
endStructure(*static_cast<const PVStructure *>(inprog.back()));
|
||||
break;
|
||||
|
||||
case structureArray:
|
||||
endStructureArray(*static_cast<const PVStructureArray *>(inprog.back()));
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false); // oops!
|
||||
return;
|
||||
}
|
||||
inprog.pop_back();
|
||||
|
||||
} else {
|
||||
// real field
|
||||
|
||||
if(!next) {
|
||||
// NULL entry in a structure array
|
||||
encodeNull();
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(next->getField()->getType()) {
|
||||
case scalar:
|
||||
encodeScalar(*static_cast<const PVScalar*>(next));
|
||||
break;
|
||||
case scalarArray:
|
||||
encodeArray(*static_cast<const PVScalarArray*>(next));
|
||||
break;
|
||||
case structure: {
|
||||
const PVStructure &fld = *static_cast<const PVStructure*>(next);
|
||||
const PVFieldPtrArray& vals = fld.getPVFields();
|
||||
|
||||
inprog.push_back(next);
|
||||
|
||||
beginStructure(fld);
|
||||
for(size_t i=0, nfld=fld.getStructure()->getNumberFields(); i<nfld; i++)
|
||||
todo.push_back(vals[i].get());
|
||||
|
||||
todo.push_back(marker);
|
||||
break;
|
||||
}
|
||||
case structureArray: {
|
||||
const PVStructureArray &fld = *static_cast<const PVStructureArray*>(next);
|
||||
PVStructureArray::const_svector vals(fld.view());
|
||||
|
||||
inprog.push_back(next);
|
||||
|
||||
beginStructureArray(fld);
|
||||
for(PVStructureArray::const_svector::const_iterator it=vals.begin();
|
||||
it!=vals.end(); ++it)
|
||||
{
|
||||
todo.push_back(it->get());
|
||||
}
|
||||
|
||||
todo.push_back(marker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PrinterPlain::PrinterPlain()
|
||||
:PrinterBase()
|
||||
,ilvl(0)
|
||||
{}
|
||||
|
||||
PrinterPlain::~PrinterPlain() {}
|
||||
|
||||
void PrinterPlain::beginStructure(const PVStructure& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getStructure()->getID() << " " << pv.getFieldName();
|
||||
String ename(pv.getExtendsStructureName());
|
||||
if(!ename.empty())
|
||||
S() << " extends " << ename;
|
||||
S() << std::endl;
|
||||
ilvl++;
|
||||
}
|
||||
|
||||
void PrinterPlain::endStructure(const PVStructure&) {ilvl--;}
|
||||
|
||||
void PrinterPlain::beginStructureArray(const PVStructureArray& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getStructureArray()->getID() << " "
|
||||
<< pv.getFieldName() << "[] ";
|
||||
ilvl++;
|
||||
}
|
||||
|
||||
void PrinterPlain::endStructureArray(const PVStructureArray&) {ilvl--;}
|
||||
|
||||
void PrinterPlain::encodeScalar(const PVScalar& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getScalar()->getID() << " "
|
||||
<< pv.getFieldName() << " "
|
||||
<< pv.getAs<String>() << std::endl;
|
||||
}
|
||||
|
||||
void PrinterPlain::encodeArray(const PVScalarArray& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
shared_vector<const String> temp;
|
||||
pv.getAs<String>(temp);
|
||||
|
||||
S() << pv.getScalarArray()->getID() << " "
|
||||
<< pv.getFieldName() << " [";
|
||||
for(size_t i=0, len=pv.getLength(); i<len; i++) {
|
||||
S() << temp[i];
|
||||
if(i!=len-1)
|
||||
S().put(',');
|
||||
}
|
||||
S() << "]" << std::endl;
|
||||
}
|
||||
|
||||
void PrinterPlain::encodeNull()
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << "NULL" << std::endl;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -379,7 +379,7 @@ public:
|
||||
* @param count The number of elements.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void putArray(T* values, std::size_t count);
|
||||
inline void putArray(const T* values, std::size_t count);
|
||||
/**
|
||||
* Get an array of type {@code T} from the byte buffer.
|
||||
* The position is adjusted.
|
||||
@@ -842,7 +842,7 @@ private:
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void ByteBuffer::putArray(T* values, std::size_t count)
|
||||
inline void ByteBuffer::putArray(const T* values, std::size_t count)
|
||||
{
|
||||
// this avoids int8 specialization, compiler will take care if optimization, -O2 or more
|
||||
if (sizeof(T) == 1)
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace detail {
|
||||
*
|
||||
* Takes advantage of the requirement that all exception classes
|
||||
* must be copy constructable. Of course this also requires
|
||||
* the and extra copy be constructed...
|
||||
* that an extra copy be constructed...
|
||||
*/
|
||||
template<typename E>
|
||||
class ExceptionMixed : public E, public ExceptionMixin {
|
||||
|
||||
467
pvDataApp/misc/parseToPOD.cpp
Normal file
467
pvDataApp/misc/parseToPOD.cpp
Normal file
@@ -0,0 +1,467 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
|
||||
#include <epicsVersion.h>
|
||||
|
||||
#include <epicsMath.h>
|
||||
#include <epicsStdlib.h>
|
||||
#include <epicsString.h>
|
||||
#include <epicsConvert.h>
|
||||
|
||||
#include "typeCast.h"
|
||||
|
||||
// need to use "long long" when sizeof(int)==sizeof(long)
|
||||
#if ULONG_MAX == 0xfffffffful
|
||||
#define NEED_LONGLONG
|
||||
#endif
|
||||
|
||||
#ifndef EPICS_VERSION_INT
|
||||
#define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
|
||||
#define EPICS_VERSION_INT VERSION_INT(EPICS_VERSION, EPICS_REVISION, EPICS_MODIFICATION, EPICS_PATCH_LEVEL)
|
||||
#endif
|
||||
|
||||
#if EPICS_VERSION_INT < VERSION_INT(3,15,0,1)
|
||||
/* integer conversion primatives added to epicsStdlib.c in 3.15.0.1 */
|
||||
|
||||
#define S_stdlib_noConversion 1 /* No digits to convert */
|
||||
#define S_stdlib_extraneous 2 /* Extraneous characters */
|
||||
#define S_stdlib_underflow 3 /* Too small to represent */
|
||||
#define S_stdlib_overflow 4 /* Too large to represent */
|
||||
#define S_stdlib_badBase 5 /* Number base not supported */
|
||||
|
||||
static int
|
||||
epicsParseLong(const char *str, long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtol(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseULong(const char *str, unsigned long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
unsigned long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtoul(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseDouble(const char *str, double *to, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
double value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = epicsStrtod(str, &endp);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == ERANGE)
|
||||
return (value == 0) ? S_stdlib_underflow : S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* These call the primitives */
|
||||
|
||||
static int
|
||||
epicsParseInt8(const char *str, epicsInt8 *to, int base, char **units)
|
||||
{
|
||||
long value;
|
||||
int status = epicsParseLong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (value < -0x80 || value > 0x7f)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseUInt8(const char *str, epicsUInt8 *to, int base, char **units)
|
||||
{
|
||||
unsigned long value;
|
||||
int status = epicsParseULong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (value > 0xff && value <= ~0xffUL)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseInt16(const char *str, epicsInt16 *to, int base, char **units)
|
||||
{
|
||||
long value;
|
||||
int status = epicsParseLong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (value < -0x8000 || value > 0x7fff)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseUInt16(const char *str, epicsUInt16 *to, int base, char **units)
|
||||
{
|
||||
unsigned long value;
|
||||
int status = epicsParseULong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (value > 0xffff && value <= ~0xffffUL)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseInt32(const char *str, epicsInt32 *to, int base, char **units)
|
||||
{
|
||||
long value;
|
||||
int status = epicsParseLong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
#if (LONG_MAX > 0x7fffffff)
|
||||
if (value < -0x80000000L || value > 0x7fffffffL)
|
||||
return S_stdlib_overflow;
|
||||
#endif
|
||||
|
||||
*to = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
|
||||
{
|
||||
unsigned long value;
|
||||
int status = epicsParseULong(str, &value, base, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
#if (ULONG_MAX > 0xffffffff)
|
||||
if (value > 0xffffffffUL && value <= ~0xffffffffUL)
|
||||
return S_stdlib_overflow;
|
||||
#endif
|
||||
|
||||
*to = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseFloat(const char *str, float *to, char **units)
|
||||
{
|
||||
double value, abs;
|
||||
int status = epicsParseDouble(str, &value, units);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
abs = fabs(value);
|
||||
if (value > 0 && abs <= FLT_MIN)
|
||||
return S_stdlib_underflow;
|
||||
if (finite(value) && abs >= FLT_MAX)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
*to = value;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(NEED_LONGLONG) && defined(__vxworks)
|
||||
static
|
||||
long long strtoll(const char *ptr, char ** endp, int base)
|
||||
{
|
||||
size_t inlen = strlen(ptr);
|
||||
long long result;
|
||||
unsigned char offset=0;
|
||||
|
||||
assert(base==0);
|
||||
|
||||
if(ptr[0]=='-')
|
||||
offset=1;
|
||||
|
||||
try {
|
||||
std::istringstream strm(ptr);
|
||||
|
||||
assert(strm.rdbuf()->in_avail()>=0
|
||||
&& inlen==(size_t)strm.rdbuf()->in_avail());
|
||||
|
||||
if(ptr[offset]=='0') {
|
||||
if(ptr[offset+1]=='x')
|
||||
strm >> std::hex;
|
||||
else
|
||||
strm >> std::oct;
|
||||
}
|
||||
|
||||
strm >> result;
|
||||
if(strm.fail())
|
||||
goto noconvert;
|
||||
|
||||
assert(strm.rdbuf()->in_avail()>=0
|
||||
&& inlen>=(size_t)strm.rdbuf()->in_avail());
|
||||
|
||||
size_t consumed = inlen - strm.rdbuf()->in_avail();
|
||||
*endp = (char*)ptr + consumed;
|
||||
|
||||
return result;
|
||||
|
||||
} catch(...) {
|
||||
goto noconvert;
|
||||
}
|
||||
|
||||
return result;
|
||||
noconvert:
|
||||
*endp = (char*)ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
unsigned long long strtoull(const char *ptr, char ** endp, int base)
|
||||
{
|
||||
size_t inlen = strlen(ptr);
|
||||
unsigned long long result;
|
||||
|
||||
assert(base==0);
|
||||
|
||||
try {
|
||||
std::istringstream strm(ptr);
|
||||
|
||||
assert(strm.rdbuf()->in_avail()>=0
|
||||
&& inlen==(size_t)strm.rdbuf()->in_avail());
|
||||
|
||||
if(ptr[0]=='0') {
|
||||
if(ptr[1]=='x')
|
||||
strm >> std::hex;
|
||||
else
|
||||
strm >> std::oct;
|
||||
}
|
||||
|
||||
strm >> result;
|
||||
if(strm.fail())
|
||||
goto noconvert;
|
||||
|
||||
assert(strm.rdbuf()->in_avail()>=0
|
||||
&& inlen>=(size_t)strm.rdbuf()->in_avail());
|
||||
|
||||
size_t consumed = inlen - strm.rdbuf()->in_avail();
|
||||
*endp = (char*)ptr + consumed;
|
||||
|
||||
return result;
|
||||
|
||||
} catch(...) {
|
||||
goto noconvert;
|
||||
}
|
||||
|
||||
return result;
|
||||
noconvert:
|
||||
*endp = (char*)ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* do we need long long? */
|
||||
#ifdef NEED_LONGLONG
|
||||
static int
|
||||
epicsParseLongLong(const char *str, long long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
long long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtoll(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
epicsParseULongLong(const char *str, unsigned long long *to, int base, char **units)
|
||||
{
|
||||
int c;
|
||||
char *endp;
|
||||
unsigned long long value;
|
||||
|
||||
while ((c = *str) && isspace(c))
|
||||
++str;
|
||||
|
||||
errno = 0;
|
||||
value = strtoull(str, &endp, base);
|
||||
|
||||
if (endp == str)
|
||||
return S_stdlib_noConversion;
|
||||
if (errno == EINVAL) /* Not universally supported */
|
||||
return S_stdlib_badBase;
|
||||
if (errno == ERANGE)
|
||||
return S_stdlib_overflow;
|
||||
|
||||
while ((c = *endp) && isspace(c))
|
||||
++endp;
|
||||
if (c && !units)
|
||||
return S_stdlib_extraneous;
|
||||
|
||||
*to = value;
|
||||
if (units)
|
||||
*units = endp;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
void handleParseError(int err)
|
||||
{
|
||||
switch(err) {
|
||||
case 0: break;
|
||||
case S_stdlib_noConversion: throw std::runtime_error("parseToPOD: No digits to convert");
|
||||
case S_stdlib_extraneous: throw std::runtime_error("parseToPOD: Extraneous characters");
|
||||
case S_stdlib_underflow: throw std::runtime_error("parseToPOD: Too small to represent");
|
||||
case S_stdlib_overflow: throw std::runtime_error("parseToPOD: Too large to represent");
|
||||
case S_stdlib_badBase: throw std::runtime_error("parseToPOD: Number base not supported");
|
||||
default:
|
||||
throw std::runtime_error("parseToPOD: unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
namespace epics { namespace pvData { namespace detail {
|
||||
|
||||
#define INTFN(T, S) \
|
||||
void parseToPOD(const std::string& in, T *out) { \
|
||||
epics ## S temp; \
|
||||
int err = epicsParse ## S (in.c_str(), &temp, 0, NULL); \
|
||||
if(err) handleParseError(err); \
|
||||
else *out = temp; \
|
||||
}
|
||||
|
||||
INTFN(char, Int8);
|
||||
INTFN(int8_t, Int8);
|
||||
INTFN(uint8_t, UInt8);
|
||||
INTFN(int16_t, Int16);
|
||||
INTFN(uint16_t, UInt16);
|
||||
INTFN(int32_t, Int32);
|
||||
INTFN(uint32_t, UInt32);
|
||||
|
||||
void parseToPOD(const std::string& in, int64_t *out) {
|
||||
#ifdef NEED_LONGLONG
|
||||
int err = epicsParseLongLong(in.c_str(), out, 0, NULL);
|
||||
#else
|
||||
int err = epicsParseLong(in.c_str(), out, 0, NULL);
|
||||
#endif
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
void parseToPOD(const std::string& in, uint64_t *out) {
|
||||
#ifdef NEED_LONGLONG
|
||||
int err = epicsParseULongLong(in.c_str(), out, 0, NULL);
|
||||
#else
|
||||
int err = epicsParseULong(in.c_str(), out, 0, NULL);
|
||||
#endif
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
void parseToPOD(const std::string& in, float *out) {
|
||||
int err = epicsParseFloat(in.c_str(), out, NULL);
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
void parseToPOD(const std::string& in, double *out) {
|
||||
int err = epicsParseDouble(in.c_str(), out, NULL);
|
||||
if(err) handleParseError(err);
|
||||
}
|
||||
|
||||
}}}
|
||||
@@ -4,7 +4,7 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Michael DavidSaver
|
||||
* @author Michael Davidsaver
|
||||
*/
|
||||
|
||||
#ifndef SHAREDPTR_H
|
||||
|
||||
1006
pvDataApp/misc/sharedVector.h
Normal file
1006
pvDataApp/misc/sharedVector.h
Normal file
File diff suppressed because it is too large
Load Diff
120
pvDataApp/misc/templateMeta.h
Normal file
120
pvDataApp/misc/templateMeta.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/** C++ Template meta programming helpers
|
||||
*/
|
||||
#ifndef TEMPLATEMETA_H
|
||||
#define TEMPLATEMETA_H
|
||||
|
||||
// gently nudge the compiler to inline our wrappers
|
||||
// Warning: Only use this when the template body is *small*.
|
||||
// You have been warned!
|
||||
#if defined(__GNUC__) && __GNUC__>=3
|
||||
# define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#elif defined(_MSC_VER)
|
||||
# define FORCE_INLINE __forceinline
|
||||
#else
|
||||
# define FORCE_INLINE inline
|
||||
#endif
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
namespace meta {
|
||||
|
||||
/** If needed, add the 'const' qualifier to the provided type.
|
||||
*
|
||||
* Avoids adding the const qualifier twice (aka 'const const int')
|
||||
@code
|
||||
assert(typeid(decorate_const<int>::type)==typeid(const int));
|
||||
assert(typeid(decorate_const<const int>::type)==typeid(const int));
|
||||
@endcode
|
||||
*/
|
||||
template<typename T> struct decorate_const { typedef const T type; };
|
||||
template<typename T> struct decorate_const<const T> { typedef const T type; };
|
||||
|
||||
/** Remove the 'const' qualifier if present
|
||||
@code
|
||||
assert(typeid(strip_const<int>::type)==typeid(int));
|
||||
assert(typeid(strip_const<const int>::type)==typeid(int));
|
||||
@endcode
|
||||
*/
|
||||
template<typename T> struct strip_const { typedef T type; };
|
||||
template<typename T> struct strip_const<const T> { typedef T type; };
|
||||
|
||||
/** test to allow specialization only when A!=B
|
||||
*
|
||||
@code
|
||||
template<typename A, typename B, class Enable = void>
|
||||
struct myTemp {...};
|
||||
|
||||
// specialization when A==B
|
||||
template<typename T>
|
||||
struct myTemp<T,T> {...};
|
||||
|
||||
// specialization for A is 'int',
|
||||
// enabler needed to remove ambiguity when B is 'int'.
|
||||
template<typename B>
|
||||
struct myTemp<int, B, typename meta::not_same_type<int,B>::type>
|
||||
{...};
|
||||
@endcode
|
||||
*/
|
||||
template<typename A, typename B, typename R = void>
|
||||
struct not_same_type {typedef R type;};
|
||||
template<typename A>
|
||||
struct not_same_type<A,A> {};
|
||||
|
||||
//! Select if both A and B have the same root type (excluding const qualifier)
|
||||
template<typename A, typename B, class R = void> struct same_root {};
|
||||
template<typename T, class R> struct same_root<T,T,R> { typedef R type; };
|
||||
template<typename T, class R> struct same_root<const T,T,R> { typedef R type; };
|
||||
template<typename T, class R> struct same_root<T,const T,R> { typedef R type; };
|
||||
|
||||
namespace detail {
|
||||
struct _const_yes {};
|
||||
struct _const_no {};
|
||||
template<typename T> struct _has_const { typedef _const_no type; };
|
||||
template<typename T> struct _has_const<const T> { typedef _const_yes type; };
|
||||
|
||||
template<typename A, typename B, class R = void> struct _same_type {};
|
||||
template<typename T, class R> struct _same_type<T,T,R> { typedef R type; };
|
||||
} // namespace detail
|
||||
|
||||
//! Check if both A and B are either const or non-const.
|
||||
template<typename A, typename B, class R = void>
|
||||
struct same_const :
|
||||
public detail::_same_type<typename detail::_has_const<A>::type,
|
||||
typename detail::_has_const<B>::type,
|
||||
R>
|
||||
{};
|
||||
|
||||
/** test if provided type is 'void' or 'const void'
|
||||
*
|
||||
* Avoid having to explicitly specialize for both
|
||||
@code
|
||||
template<typename A, class Enable = void>
|
||||
struct myTemp {...};
|
||||
|
||||
// specialization when A is 'void' or 'const void'
|
||||
template<typename A>
|
||||
struct myTemp<A, typename meta::is_void<A>::type> {...};
|
||||
@endcode
|
||||
*/
|
||||
template<typename T, class R = void> struct is_void {};
|
||||
template<class R> struct is_void<void,R> { typedef R type; };
|
||||
template<class R> struct is_void<const void,R> { typedef R type; };
|
||||
|
||||
//! Inverse of is_void<T>
|
||||
template<typename T, class R = void> struct is_not_void { typedef R type; };
|
||||
template<> struct is_not_void<void> {};
|
||||
template<> struct is_not_void<const void> {};
|
||||
|
||||
//! Enabler to ensure that both conditions A and B are true
|
||||
template<typename A, typename B, class EnableA = void, class EnableB = void, class R = void>
|
||||
struct _and {};
|
||||
template<typename A, typename B, class R>
|
||||
struct _and<A,B, typename A::type, typename B::type, R> { typedef R type; };
|
||||
|
||||
}}}
|
||||
|
||||
#endif // TEMPLATEMETA_H
|
||||
230
pvDataApp/misc/typeCast.cpp
Normal file
230
pvDataApp/misc/typeCast.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Author: Michael Davidsaver */
|
||||
#include <algorithm>
|
||||
|
||||
#include "typeCast.h"
|
||||
|
||||
using epics::pvData::castUnsafe;
|
||||
using epics::pvData::String;
|
||||
using epics::pvData::ScalarType;
|
||||
using epics::pvData::pvString;
|
||||
|
||||
namespace {
|
||||
|
||||
static void noconvert(size_t, void*, const void*)
|
||||
{
|
||||
throw std::runtime_error("castUnsafeV: Conversion not supported");
|
||||
}
|
||||
|
||||
template<typename TO, typename FROM>
|
||||
static void castVTyped(size_t count, void *draw, const void *sraw)
|
||||
{
|
||||
TO *dest=(TO*)draw;
|
||||
const FROM *src=(FROM*)sraw;
|
||||
std::transform(src, src+count, dest, castUnsafe<TO,FROM>);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void copyV(size_t count, void *draw, const void *sraw)
|
||||
{
|
||||
T *dest=(T*)draw;
|
||||
const T *src=(T*)sraw;
|
||||
std::copy(src, src+count, dest);
|
||||
}
|
||||
|
||||
typedef void (*convertfn)(size_t, void*, const void*);
|
||||
|
||||
/* lookup table of converter functions.
|
||||
* first dimension is TO, second is FROM
|
||||
*/
|
||||
static convertfn converters[pvString+1][pvString+1] =
|
||||
{
|
||||
// to pvBoolean
|
||||
{ &noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert,
|
||||
&noconvert
|
||||
},
|
||||
// to pvByte
|
||||
{&noconvert,
|
||||
©V<int8_t>,
|
||||
&castVTyped<int8_t, int16_t>,
|
||||
&castVTyped<int8_t, int32_t>,
|
||||
&castVTyped<int8_t, int64_t>,
|
||||
&castVTyped<int8_t, uint8_t>,
|
||||
&castVTyped<int8_t, uint16_t>,
|
||||
&castVTyped<int8_t, uint32_t>,
|
||||
&castVTyped<int8_t, uint64_t>,
|
||||
&castVTyped<int8_t, float>,
|
||||
&castVTyped<int8_t, double>,
|
||||
&castVTyped<int8_t, String>,
|
||||
},
|
||||
// to pvShort
|
||||
{&noconvert,
|
||||
&castVTyped<int16_t, int8_t>,
|
||||
©V<int16_t>,
|
||||
&castVTyped<int16_t, int32_t>,
|
||||
&castVTyped<int16_t, int64_t>,
|
||||
&castVTyped<int16_t, uint8_t>,
|
||||
&castVTyped<int16_t, uint16_t>,
|
||||
&castVTyped<int16_t, uint32_t>,
|
||||
&castVTyped<int16_t, uint64_t>,
|
||||
&castVTyped<int16_t, float>,
|
||||
&castVTyped<int16_t, double>,
|
||||
&castVTyped<int16_t, String>,
|
||||
},
|
||||
// to pvInt
|
||||
{&noconvert,
|
||||
&castVTyped<int32_t, int8_t>,
|
||||
&castVTyped<int32_t, int16_t>,
|
||||
©V<int32_t>,
|
||||
&castVTyped<int32_t, int64_t>,
|
||||
&castVTyped<int32_t, uint8_t>,
|
||||
&castVTyped<int32_t, uint16_t>,
|
||||
&castVTyped<int32_t, uint32_t>,
|
||||
&castVTyped<int32_t, uint64_t>,
|
||||
&castVTyped<int32_t, float>,
|
||||
&castVTyped<int32_t, double>,
|
||||
&castVTyped<int32_t, String>,
|
||||
},
|
||||
// to pvLong
|
||||
{&noconvert,
|
||||
&castVTyped<int64_t, int8_t>,
|
||||
&castVTyped<int64_t, int16_t>,
|
||||
&castVTyped<int64_t, int32_t>,
|
||||
©V<int64_t>,
|
||||
&castVTyped<int64_t, uint8_t>,
|
||||
&castVTyped<int64_t, uint16_t>,
|
||||
&castVTyped<int64_t, uint32_t>,
|
||||
&castVTyped<int64_t, uint64_t>,
|
||||
&castVTyped<int64_t, float>,
|
||||
&castVTyped<int64_t, double>,
|
||||
&castVTyped<int64_t, String>,
|
||||
},
|
||||
// to pvUByte
|
||||
{&noconvert,
|
||||
&castVTyped<uint8_t, int8_t>,
|
||||
&castVTyped<uint8_t, int16_t>,
|
||||
&castVTyped<uint8_t, int32_t>,
|
||||
&castVTyped<uint8_t, uint64_t>,
|
||||
©V<uint8_t>,
|
||||
&castVTyped<uint8_t, uint16_t>,
|
||||
&castVTyped<uint8_t, uint32_t>,
|
||||
&castVTyped<uint8_t, uint64_t>,
|
||||
&castVTyped<uint8_t, float>,
|
||||
&castVTyped<uint8_t, double>,
|
||||
&castVTyped<uint8_t, String>,
|
||||
},
|
||||
// to pvUShort
|
||||
{&noconvert,
|
||||
&castVTyped<uint16_t, int8_t>,
|
||||
&castVTyped<uint16_t, int16_t>,
|
||||
&castVTyped<uint16_t, int32_t>,
|
||||
&castVTyped<uint16_t, uint64_t>,
|
||||
&castVTyped<uint16_t, uint8_t>,
|
||||
©V<uint16_t>,
|
||||
&castVTyped<uint16_t, uint32_t>,
|
||||
&castVTyped<uint16_t, uint64_t>,
|
||||
&castVTyped<uint16_t, float>,
|
||||
&castVTyped<uint16_t, double>,
|
||||
&castVTyped<uint16_t, String>,
|
||||
},
|
||||
// to pvUInt
|
||||
{&noconvert,
|
||||
&castVTyped<uint32_t, int8_t>,
|
||||
&castVTyped<uint32_t, int16_t>,
|
||||
&castVTyped<uint32_t, int32_t>,
|
||||
&castVTyped<uint32_t, uint64_t>,
|
||||
&castVTyped<uint32_t, uint8_t>,
|
||||
&castVTyped<uint32_t, uint16_t>,
|
||||
©V<uint32_t>,
|
||||
&castVTyped<uint32_t, uint64_t>,
|
||||
&castVTyped<uint32_t, float>,
|
||||
&castVTyped<uint32_t, double>,
|
||||
&castVTyped<uint32_t, String>,
|
||||
},
|
||||
// to pvULong
|
||||
{&noconvert,
|
||||
&castVTyped<uint64_t, int8_t>,
|
||||
&castVTyped<uint64_t, int16_t>,
|
||||
&castVTyped<uint64_t, int32_t>,
|
||||
&castVTyped<uint64_t, uint64_t>,
|
||||
&castVTyped<uint64_t, uint8_t>,
|
||||
&castVTyped<uint64_t, uint16_t>,
|
||||
&castVTyped<uint64_t, uint32_t>,
|
||||
©V<uint64_t>,
|
||||
&castVTyped<uint64_t, float>,
|
||||
&castVTyped<uint64_t, double>,
|
||||
&castVTyped<uint64_t, String>,
|
||||
},
|
||||
// to pvFloat
|
||||
{&noconvert,
|
||||
&castVTyped<float, int8_t>,
|
||||
&castVTyped<float, int16_t>,
|
||||
&castVTyped<float, int32_t>,
|
||||
&castVTyped<float, uint64_t>,
|
||||
&castVTyped<float, uint8_t>,
|
||||
&castVTyped<float, uint16_t>,
|
||||
&castVTyped<float, uint32_t>,
|
||||
&castVTyped<float, uint64_t>,
|
||||
©V<float>,
|
||||
&castVTyped<float, double>,
|
||||
&castVTyped<float, String>,
|
||||
},
|
||||
// to pvDouble
|
||||
{&noconvert,
|
||||
&castVTyped<double, int8_t>,
|
||||
&castVTyped<double, int16_t>,
|
||||
&castVTyped<double, int32_t>,
|
||||
&castVTyped<double, uint64_t>,
|
||||
&castVTyped<double, uint8_t>,
|
||||
&castVTyped<double, uint16_t>,
|
||||
&castVTyped<double, uint32_t>,
|
||||
&castVTyped<double, uint64_t>,
|
||||
&castVTyped<double, float>,
|
||||
©V<double>,
|
||||
&castVTyped<double, String>,
|
||||
},
|
||||
// to pvString
|
||||
{&noconvert,
|
||||
&castVTyped<String, int8_t>,
|
||||
&castVTyped<String, int16_t>,
|
||||
&castVTyped<String, int32_t>,
|
||||
&castVTyped<String, uint64_t>,
|
||||
&castVTyped<String, uint8_t>,
|
||||
&castVTyped<String, uint16_t>,
|
||||
&castVTyped<String, uint32_t>,
|
||||
&castVTyped<String, uint64_t>,
|
||||
&castVTyped<String, float>,
|
||||
&castVTyped<String, double>,
|
||||
©V<String>,
|
||||
},
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
void castUnsafeV(size_t count, ScalarType to, void *dest, ScalarType from, const void *src)
|
||||
{
|
||||
unsigned int ito=to, ifrom=from;
|
||||
|
||||
if(ito>pvString || ifrom>pvString)
|
||||
throw std::runtime_error("castUnsafeV: Invalid types");
|
||||
|
||||
converters[ito][ifrom](count, dest, src);
|
||||
}
|
||||
|
||||
}}
|
||||
172
pvDataApp/misc/typeCast.h
Normal file
172
pvDataApp/misc/typeCast.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Author: Michael Davidsaver */
|
||||
#ifndef PVTYPECAST_H
|
||||
#define PVTYPECAST_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
#include <epicsConvert.h>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/templateMeta.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
typedef std::string String;
|
||||
|
||||
namespace detail {
|
||||
// parseToPOD wraps the epicsParse*() functions in one name
|
||||
// and throws exceptions
|
||||
void parseToPOD(const std::string&, char *out);
|
||||
void parseToPOD(const std::string&, int8_t *out);
|
||||
void parseToPOD(const std::string&, uint8_t *out);
|
||||
void parseToPOD(const std::string&, int16_t *out);
|
||||
void parseToPOD(const std::string&, uint16_t *out);
|
||||
void parseToPOD(const std::string&, int32_t *out);
|
||||
void parseToPOD(const std::string&, uint32_t *out);
|
||||
void parseToPOD(const std::string&, int64_t *out);
|
||||
void parseToPOD(const std::string&, uint64_t *out);
|
||||
void parseToPOD(const std::string&, float *out);
|
||||
void parseToPOD(const std::string&, double *out);
|
||||
|
||||
/* want to pass POD types by value,
|
||||
* and String by const reference
|
||||
*/
|
||||
template<typename ARG>
|
||||
struct cast_arg { typedef ARG arg; };
|
||||
template<>
|
||||
struct cast_arg<String> { typedef const String& arg; };
|
||||
|
||||
// trick std::ostream into treating char's as numbers
|
||||
// by promoting char to int
|
||||
template<typename T>
|
||||
struct print_cast { typedef T type; };
|
||||
template<>
|
||||
struct print_cast<char> { typedef int type; };
|
||||
template<>
|
||||
struct print_cast<signed char> { typedef signed int type; };
|
||||
template<>
|
||||
struct print_cast<unsigned char> { typedef unsigned int type; };
|
||||
|
||||
// default to C++ type casting
|
||||
template<typename TO, typename FROM, class Enable = void>
|
||||
struct cast_helper {
|
||||
static FORCE_INLINE TO op(FROM from) {
|
||||
return static_cast<TO>(from);
|
||||
}
|
||||
};
|
||||
|
||||
// special handling when down-casting double to float
|
||||
template<>
|
||||
struct cast_helper<float, double> {
|
||||
static FORCE_INLINE float op(double from) {
|
||||
return epicsConvertDoubleToFloat(from);
|
||||
}
|
||||
};
|
||||
|
||||
// print POD to string
|
||||
// when String!=FROM
|
||||
template<typename FROM>
|
||||
struct cast_helper<String, FROM, typename meta::not_same_type<String,FROM>::type> {
|
||||
static String op(FROM from) {
|
||||
typedef typename print_cast<FROM>::type ptype;
|
||||
std::ostringstream strm;
|
||||
strm << (ptype)from;
|
||||
if(strm.fail())
|
||||
throw std::runtime_error("Cast to string failed");
|
||||
return strm.str();
|
||||
}
|
||||
};
|
||||
|
||||
// parse POD from string
|
||||
// TO!=String
|
||||
template<typename TO>
|
||||
struct cast_helper<TO, String, typename meta::not_same_type<TO,String>::type> {
|
||||
static FORCE_INLINE TO op(const String& from) {
|
||||
TO ret;
|
||||
parseToPOD(from, &ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
} // end detail
|
||||
|
||||
/** @brief Casting/converting between supported scalar types.
|
||||
*
|
||||
* Supported types: uint8_t, int8_t, uint16_t, int16_t,
|
||||
* uint32_t, int32_t, uint64_t, int64_t,
|
||||
* float, double, String
|
||||
*
|
||||
* As defined in pvType.h
|
||||
*
|
||||
@throws std::runtime_error when the cast is not possible.
|
||||
@throws std::bad_alloc when the cast is not possible.
|
||||
*
|
||||
@section convertg Conversion Guarantees
|
||||
*
|
||||
* Conversions which always produce a correct result.
|
||||
*
|
||||
* - signed integer -> larger signed integer
|
||||
* - unsigned integer -> larger unsigned integer
|
||||
* - integer -> float or double (where sizeof(integer)<sizeof(floating))
|
||||
* - float -> double
|
||||
*
|
||||
* Conversions where out of range inputs always produce
|
||||
* a defined result, but may not be reversable.
|
||||
*
|
||||
* - double -> float. When abs(value) is outside the range
|
||||
* [FLT_MIN, FLT_MAX] the value is clipped to FLT_MIN or FLT_MAX
|
||||
* with the sign preserved.
|
||||
*
|
||||
* Conversions where invalid or out of range inputs result
|
||||
* in an exception.
|
||||
*
|
||||
* - non-String -> String
|
||||
* - String -> non-String
|
||||
* - String -> String (throws only std::bad_alloc)
|
||||
*
|
||||
* Conversions where out of range inputs produce undefined
|
||||
* results.
|
||||
*
|
||||
* - signed integer -> smaller signed integer
|
||||
* - unsigned integer -> smaller unsigned integer
|
||||
* - signed integer <-> unsigned integer
|
||||
* - integer -> float or double (where sizeof(integer)>=sizeof(floating))
|
||||
* - float or double -> integer. The floating point value
|
||||
* is rounded towards zero. However, the result for values
|
||||
* too large to be represented by the integer type
|
||||
* is not defined.
|
||||
*
|
||||
@section stringf String formats
|
||||
*
|
||||
* - Numbers beginning with 1-9 are parsed as base-10.
|
||||
* - Numbers beginning with '0x' are parsed as base-16
|
||||
* - Numbers beginning with '0' are parsed as base-8.
|
||||
* - Hex numbers are case insensitive.
|
||||
* - Exponential numbers may use either 'e' or 'E'.
|
||||
*/
|
||||
template<typename TO, typename FROM>
|
||||
static FORCE_INLINE TO castUnsafe(const FROM& from)
|
||||
{
|
||||
return detail::cast_helper<TO,FROM>::op(from);
|
||||
}
|
||||
|
||||
void castUnsafeV(size_t count, ScalarType to, void *dest, ScalarType from, const void *src);
|
||||
|
||||
//! Cast value to printable type
|
||||
//! A no-op except for char types, which are cast to int
|
||||
//! so that they are printed as numbers std::ostream operators.
|
||||
template<typename T>
|
||||
static FORCE_INLINE
|
||||
typename detail::print_cast<T>::type
|
||||
print_cast(const T& v) { return v; }
|
||||
|
||||
}} // end namespace
|
||||
|
||||
#endif // PVTYPECAST_H
|
||||
@@ -78,9 +78,8 @@ String PVEnumerated::getChoice()
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
int index = pvIndex->get();
|
||||
StringArrayData data;
|
||||
pvChoices->get(0,pvChoices->getLength(),data);
|
||||
return data.data[index];
|
||||
const PVStringArray::const_svector& data(pvChoices->view());
|
||||
return data[index];
|
||||
}
|
||||
|
||||
bool PVEnumerated::choicesMutable()
|
||||
@@ -91,15 +90,6 @@ bool PVEnumerated::choicesMutable()
|
||||
return pvChoices->isImmutable();
|
||||
}
|
||||
|
||||
StringArrayPtr const & PVEnumerated:: getChoices()
|
||||
{
|
||||
if(pvIndex.get()==NULL ) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
StringArrayData data;
|
||||
return pvChoices->getSharedVector();
|
||||
}
|
||||
|
||||
int32 PVEnumerated::getNumberChoices()
|
||||
{
|
||||
if(pvIndex.get()==NULL ) {
|
||||
@@ -108,13 +98,15 @@ int32 PVEnumerated::getNumberChoices()
|
||||
return pvChoices->getLength();
|
||||
}
|
||||
|
||||
bool PVEnumerated:: setChoices(StringArray & choices)
|
||||
bool PVEnumerated:: setChoices(const StringArray & choices)
|
||||
{
|
||||
if(pvIndex.get()==NULL ) {
|
||||
throw std::logic_error(notAttached);
|
||||
}
|
||||
if(pvChoices->isImmutable()) return false;
|
||||
pvChoices->put(0,choices.size(),get(choices),0);
|
||||
PVStringArray::svector data(choices.size());
|
||||
std::copy(choices.begin(), choices.end(), data.begin());
|
||||
pvChoices->replace(freeze(data));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ public:
|
||||
int32 getIndex();
|
||||
String getChoice();
|
||||
bool choicesMutable();
|
||||
StringArrayPtr const & getChoices();
|
||||
inline PVStringArray::const_svector getChoices(){return pvChoices->view();}
|
||||
int32 getNumberChoices();
|
||||
bool setChoices(StringArray & choices);
|
||||
bool setChoices(const StringArray & choices);
|
||||
private:
|
||||
static String notFound;
|
||||
static String notAttached;
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
bool operator==(PVField&, PVField&);
|
||||
bool operator==(const PVField&, const PVField&);
|
||||
|
||||
static inline bool operator!=(PVField& a, PVField& b)
|
||||
static inline bool operator!=(const PVField& a, const PVField& b)
|
||||
{return !(a==b);}
|
||||
|
||||
|
||||
@@ -71,13 +71,16 @@ typedef std::tr1::shared_ptr<Convert> ConvertPtr;
|
||||
class Convert {
|
||||
public:
|
||||
static ConvertPtr getConvert();
|
||||
~Convert();
|
||||
/**
|
||||
* Get the full fieldName for the pvField.
|
||||
* @param builder The builder that will have the result.
|
||||
* @param pvField The pvField.
|
||||
*/
|
||||
void getFullName(StringBuilder buf,PVFieldPtr const & pvField);
|
||||
void getFullName(StringBuilder buf,PVFieldPtr const & pvField)
|
||||
{
|
||||
*buf = pvField->getFullName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do fields have the same definition.
|
||||
*
|
||||
@@ -85,7 +88,11 @@ public:
|
||||
* @param Second field
|
||||
* @return (false, true) if the fields (are not, are) the same.
|
||||
*/
|
||||
bool equals(PVFieldPtr const &a,PVFieldPtr const &b);
|
||||
inline bool equals(PVFieldPtr const &a,PVFieldPtr const &b)
|
||||
{
|
||||
return *a==*b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do fields have the same definition.
|
||||
*
|
||||
@@ -93,7 +100,11 @@ public:
|
||||
* @param Second field
|
||||
* @return (false, true) if the fields (are not, are) the same.
|
||||
*/
|
||||
bool equals(PVField &a,PVField &b);
|
||||
inline bool equals(PVField &a,PVField &b)
|
||||
{
|
||||
return a==b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* @param buf buffer for the result
|
||||
@@ -101,14 +112,16 @@ public:
|
||||
* If a PVField is a structure or array be prepared for a very long string.
|
||||
* @param indentLevel indentation level
|
||||
*/
|
||||
void getString(StringBuilder buf,PVFieldPtr const & pvField,int indentLevel);
|
||||
inline void getString(StringBuilder buf,PVFieldPtr const & pvField,int indentLevel)
|
||||
{getString(buf, pvField.get(), indentLevel);}
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* param buf buffer for the result
|
||||
* @param pv The PVField to convert to a string.
|
||||
* If the PVField is a structure or array be prepared for a very long string.
|
||||
*/
|
||||
void getString(StringBuilder buf,PVFieldPtr const & pvField);
|
||||
inline void getString(StringBuilder buf,PVFieldPtr const & pvField)
|
||||
{getString(buf, pvField.get(), 0);}
|
||||
/**
|
||||
* Convert a PVField to a string.
|
||||
* @param buf buffer for the result
|
||||
@@ -123,7 +136,8 @@ public:
|
||||
* @param pv The PVField to convert to a string.
|
||||
* If the PVField is a structure or array be prepared for a very long string.
|
||||
*/
|
||||
void getString(StringBuilder buf,PVField const * pvField);
|
||||
inline void getString(StringBuilder buf,PVField const * pvField)
|
||||
{getString(buf, pvField, 0);}
|
||||
/**
|
||||
* Convert from an array of String to a PVScalar
|
||||
* @param pv The PV.
|
||||
@@ -141,7 +155,11 @@ public:
|
||||
* @param from The String value to convert and put into a PV.
|
||||
* @throws std::logic_error if the String does not have a valid value.
|
||||
*/
|
||||
void fromString(PVScalarPtr const & pv, String const & from);
|
||||
void fromString(PVScalarPtr const & pv, String const & from)
|
||||
{
|
||||
pv->putFrom<String>(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from a String to a PVScalarArray.
|
||||
* The String must be a comma separated set of values optionally enclosed in []
|
||||
@@ -235,22 +253,6 @@ public:
|
||||
bool isCopyScalarArrayCompatible(
|
||||
ScalarArrayConstPtr const & from,
|
||||
ScalarArrayConstPtr const & to);
|
||||
/**
|
||||
* Convert from a source PV array to a destination PV array.
|
||||
* @param from The source array.
|
||||
* @param offset Starting element in the source.
|
||||
* @param to The destination array.
|
||||
* @param toOffset Starting element in the array.
|
||||
* @param length Number of elements to transfer.
|
||||
* @return Number of elements converted.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
std::size_t copyScalarArray(
|
||||
PVScalarArrayPtr const & from,
|
||||
std::size_t offset,
|
||||
PVScalarArrayPtr const & to,
|
||||
std::size_t toOffset,
|
||||
std::size_t length);
|
||||
/**
|
||||
* Are from and to valid arguments for copyStructure.
|
||||
* They are only compatible if they have the same Structure description.
|
||||
@@ -294,459 +296,146 @@ public:
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
int8 toByte(PVScalarPtr const & pv);
|
||||
inline int8 toByte(PVScalarPtr const & pv) { return pv->getAs<int8>();}
|
||||
/**
|
||||
* Convert a PV to a short.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
int16 toShort(PVScalarPtr const & pv);
|
||||
inline int16 toShort(PVScalarPtr const & pv) { return pv->getAs<int16>();}
|
||||
/**
|
||||
* Convert a PV to a int.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
int32 toInt(PVScalarPtr const & pv);
|
||||
inline int32 toInt(PVScalarPtr const & pv) { return pv->getAs<int32>();}
|
||||
/**
|
||||
* Convert a PV to an long
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
int64 toLong(PVScalarPtr const & pv);
|
||||
inline int64 toLong(PVScalarPtr const & pv) { return pv->getAs<int32>();}
|
||||
/**
|
||||
* Convert a PV to a ubyte.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
uint8 toUByte(PVScalarPtr const & pv);
|
||||
inline uint8 toUByte(PVScalarPtr const & pv) { return pv->getAs<uint8>();}
|
||||
/**
|
||||
* Convert a PV to a ushort.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
uint16 toUShort(PVScalarPtr const & pv);
|
||||
inline uint16 toUShort(PVScalarPtr const & pv) { return pv->getAs<uint16>();}
|
||||
/**
|
||||
* Convert a PV to a uint.
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
uint32 toUInt(PVScalarPtr const & pv);
|
||||
inline uint32 toUInt(PVScalarPtr const & pv) { return pv->getAs<uint32>();}
|
||||
/**
|
||||
* Convert a PV to an ulong
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
uint64 toULong(PVScalarPtr const & pv);
|
||||
inline uint64 toULong(PVScalarPtr const & pv) { return pv->getAs<uint64>();}
|
||||
/**
|
||||
* Convert a PV to a float
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
float toFloat(PVScalarPtr const & pv);
|
||||
inline float toFloat(PVScalarPtr const & pv) { return pv->getAs<float>();}
|
||||
/**
|
||||
* Convert a PV to a double
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
double toDouble(PVScalarPtr const & pv);
|
||||
inline double toDouble(PVScalarPtr const & pv) { return pv->getAs<double>();}
|
||||
/**
|
||||
* Convert a PV to a String
|
||||
* @param pv a PV
|
||||
* @return converted value
|
||||
*/
|
||||
String toString(PVScalarPtr const & pv);
|
||||
inline String toString(PVScalarPtr const & pv) { return pv->getAs<String>();}
|
||||
/**
|
||||
* Convert a PV from a byte
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromByte(PVScalarPtr const & pv,int8 from);
|
||||
inline void fromByte(PVScalarPtr const & pv,int8 from) { pv->putFrom<int8>(from); }
|
||||
/**
|
||||
* Convert a PV from a short
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromShort(PVScalarPtr const & pv,int16 from);
|
||||
inline void fromShort(PVScalarPtr const & pv,int16 from) { pv->putFrom<int16>(from); }
|
||||
/**
|
||||
* Convert a PV from an int
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromInt(PVScalarPtr const & pv, int32 from);
|
||||
inline void fromInt(PVScalarPtr const & pv, int32 from) { pv->putFrom<int32>(from); }
|
||||
/**
|
||||
* Convert a PV from a long
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromLong(PVScalarPtr const & pv, int64 from);
|
||||
inline void fromLong(PVScalarPtr const & pv, int64 from) { pv->putFrom<int64>(from); }
|
||||
/**
|
||||
* Convert a PV from a ubyte
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromUByte(PVScalarPtr const & pv,uint8 from);
|
||||
inline void fromUByte(PVScalarPtr const & pv,uint8 from) { pv->putFrom<uint8>(from); }
|
||||
/**
|
||||
* Convert a PV from a ushort
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromUShort(PVScalarPtr const & pv,uint16 from);
|
||||
inline void fromUShort(PVScalarPtr const & pv,uint16 from) { pv->putFrom<uint16>(from); }
|
||||
/**
|
||||
* Convert a PV from an uint
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromUInt(PVScalarPtr const & pv, uint32 from);
|
||||
inline void fromUInt(PVScalarPtr const & pv, uint32 from) { pv->putFrom<uint32>(from); }
|
||||
/**
|
||||
* Convert a PV from a ulong
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromULong(PVScalarPtr const & pv, uint64 from);
|
||||
inline void fromULong(PVScalarPtr const & pv, uint64 from) { pv->putFrom<uint64>(from); }
|
||||
/**
|
||||
* Convert a PV from a float
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromFloat(PVScalarPtr const & pv, float from);
|
||||
inline void fromFloat(PVScalarPtr const & pv, float from) { pv->putFrom<float>(from); }
|
||||
/**
|
||||
* Convert a PV from a double
|
||||
* @param pv a PV
|
||||
* @param from value to put into PV
|
||||
* @throws std::invalid_argument if the Type is not a numeric scalar
|
||||
*/
|
||||
void fromDouble(PVScalarPtr const & pv, double from);
|
||||
/**
|
||||
* Convert a PV array to a byte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toByteArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int8* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a short array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toShortArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int16* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to an int array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toIntArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int32* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a long array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toLongArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
int64* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a ubyte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toUByteArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint8* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a ushort array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toUShortArray(PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint16* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to an uint array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toUIntArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint32* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a ulong array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toULongArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
uint64* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a float array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toFloatArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
float* to,
|
||||
std::size_t toOffset);
|
||||
/**
|
||||
* Convert a PV array to a double array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param to where to put the PV data
|
||||
* @param toOffset starting element in the array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t toDoubleArray(
|
||||
PVScalarArrayPtr const & pv,
|
||||
std::size_t offset,
|
||||
std::size_t length,
|
||||
double* to, std::size_t
|
||||
toOffset);
|
||||
/**
|
||||
* Convert a PV array from a byte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int8* from, std::size_t fromOffset);
|
||||
std::size_t fromByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const ByteArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a short array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int16* from, std::size_t fromOffset);
|
||||
std::size_t fromShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const ShortArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from an int array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int32* from, std::size_t fromOffset);
|
||||
std::size_t fromIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const IntArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a long array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromLongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const int64* from, std::size_t fromOffset);
|
||||
std::size_t fromLongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const LongArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a ubyte array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromUByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint8* from, std::size_t fromOffset);
|
||||
std::size_t fromUByteArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const UByteArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a ushort array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromUShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint16* from, std::size_t fromOffset);
|
||||
std::size_t fromUShortArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const UShortArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from an uint array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromUIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint32* from, std::size_t fromOffset);
|
||||
std::size_t fromUIntArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const UIntArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a ulong array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromULongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const uint64* from, std::size_t fromOffset);
|
||||
std::size_t fromULongArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const ULongArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a float array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromFloatArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const float* from, std::size_t fromOffset);
|
||||
std::size_t fromFloatArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const FloatArray & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Convert a PV array from a double array.
|
||||
* @param pv a PV
|
||||
* @param offset starting element in a PV
|
||||
* @param length number of elements to transfer
|
||||
* @param from value to put into PV
|
||||
* @param fromOffset starting element in the source array
|
||||
* @return number of elements converted
|
||||
* @throws std::invalid_argument if the element type is not numeric
|
||||
*/
|
||||
std::size_t fromDoubleArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const double* from, std::size_t fromOffset);
|
||||
std::size_t fromDoubleArray(
|
||||
PVScalarArrayPtr & pv, std::size_t offset, std::size_t length,
|
||||
const DoubleArray & from, std::size_t fromOffset);
|
||||
inline void fromDouble(PVScalarPtr const & pv, double from) { pv->putFrom<double>(from); }
|
||||
|
||||
/**
|
||||
* Convenience method for implementing toString.
|
||||
* It generates a newline and inserts blanks at the beginning of the newline.
|
||||
@@ -754,15 +443,9 @@ public:
|
||||
* @param indentLevel Indent level, Each level is four spaces.
|
||||
*/
|
||||
void newLine(StringBuilder buf, int indentLevel);
|
||||
private:
|
||||
Convert();
|
||||
PVDataCreatePtr pvDataCreate;
|
||||
String trueString;
|
||||
String falseString;
|
||||
String illegalScalarType;
|
||||
};
|
||||
|
||||
extern ConvertPtr getConvert();
|
||||
static inline ConvertPtr getConvert() { return Convert::getConvert(); }
|
||||
|
||||
}}
|
||||
#endif /* CONVERT_H */
|
||||
|
||||
60
pvDataApp/pv/printer.h
Normal file
60
pvDataApp/pv/printer.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef PRINTER_H
|
||||
#define PRINTER_H
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include "pvData.h"
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
class PrinterBase
|
||||
{
|
||||
public:
|
||||
virtual void setStream(std::ostream&);
|
||||
virtual void clearStream();
|
||||
|
||||
virtual void print(const PVField&);
|
||||
|
||||
protected:
|
||||
PrinterBase();
|
||||
virtual ~PrinterBase()=0;
|
||||
|
||||
virtual void beginStructure(const PVStructure&);
|
||||
virtual void endStructure(const PVStructure&);
|
||||
|
||||
virtual void beginStructureArray(const PVStructureArray&);
|
||||
virtual void endStructureArray(const PVStructureArray&);
|
||||
|
||||
virtual void encodeScalar(const PVScalar&);
|
||||
virtual void encodeArray(const PVScalarArray&);
|
||||
virtual void encodeNull();
|
||||
|
||||
inline std::ostream& S() { return *strm; }
|
||||
|
||||
void impl_print(const PVField&);
|
||||
private:
|
||||
std::ostream *strm;
|
||||
};
|
||||
|
||||
class PrinterPlain : public PrinterBase
|
||||
{
|
||||
size_t ilvl;
|
||||
protected:
|
||||
virtual void beginStructure(const PVStructure&);
|
||||
virtual void endStructure(const PVStructure&);
|
||||
|
||||
virtual void beginStructureArray(const PVStructureArray&);
|
||||
virtual void endStructureArray(const PVStructureArray&);
|
||||
|
||||
virtual void encodeScalar(const PVScalar&);
|
||||
virtual void encodeArray(const PVScalarArray&);
|
||||
virtual void encodeNull();
|
||||
|
||||
public:
|
||||
PrinterPlain();
|
||||
virtual ~PrinterPlain();
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // PRINTER_H
|
||||
@@ -9,6 +9,15 @@
|
||||
*/
|
||||
#ifndef PVDATA_H
|
||||
#define PVDATA_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define USAGE_DEPRECATED __attribute__((deprecated))
|
||||
#define USAGE_ERROR(MSG) __attribute__((error(MSG)))
|
||||
#else
|
||||
#define USAGE_DEPRECATED
|
||||
#define USAGE_ERROR(MSG)
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
@@ -18,6 +27,8 @@
|
||||
#include <iomanip>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/requester.h>
|
||||
#include <pv/typeCast.h>
|
||||
#include <pv/sharedVector.h>
|
||||
|
||||
#if defined(__vxworks) && !defined(_WRS_VXWORKS_MAJOR)
|
||||
typedef class std::ios std::ios_base;
|
||||
@@ -96,7 +107,11 @@ class PVScalar;
|
||||
class PVScalarArray;
|
||||
|
||||
class PVStructure;
|
||||
class PVStructureArray;
|
||||
|
||||
|
||||
template<typename T> class PVScalarValue;
|
||||
template<typename T> class PVValueArray;
|
||||
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a PVAuxInfo.
|
||||
@@ -143,6 +158,8 @@ typedef std::vector<PVStructurePtr>::const_iterator PVStructurePtrArray_const__i
|
||||
/**
|
||||
* typedef for a pointer to a PVStructureArray.
|
||||
*/
|
||||
|
||||
typedef PVValueArray<PVStructurePtr> PVStructureArray;
|
||||
typedef std::tr1::shared_ptr<PVStructureArray> PVStructureArrayPtr;
|
||||
typedef std::vector<PVStructureArrayPtr> PVStructureArrayPtrArray;
|
||||
typedef std::tr1::shared_ptr<PVStructureArrayPtrArray> PVStructureArrayPtrArrayPtr;
|
||||
@@ -249,7 +266,13 @@ public:
|
||||
* Get the fieldName for this field.
|
||||
* @return The name or empty string if top level field.
|
||||
*/
|
||||
String getFieldName() const ;
|
||||
inline const String& getFieldName() const {return fieldName;}
|
||||
/**
|
||||
* Fully expand the name of this field using the
|
||||
* names of its parent fields with a dot '.' seperating
|
||||
* each name.
|
||||
*/
|
||||
String getFullName() const;
|
||||
/**
|
||||
* Register the message requester.
|
||||
* At most one requester can be registered.
|
||||
@@ -348,6 +371,7 @@ public:
|
||||
*/
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const = 0;
|
||||
|
||||
|
||||
protected:
|
||||
PVField::shared_pointer getPtrSelf()
|
||||
{
|
||||
@@ -370,7 +394,6 @@ private:
|
||||
bool immutable;
|
||||
RequesterPtr requester;
|
||||
PostHandlerPtr postHandler;
|
||||
std::tr1::shared_ptr<class Convert> convert;
|
||||
friend class PVDataCreate;
|
||||
friend class PVStructure;
|
||||
};
|
||||
@@ -381,6 +404,10 @@ std::ostream& operator<<(std::ostream& o, const PVField& f);
|
||||
* PVScalar is the base class for each scalar field.
|
||||
*/
|
||||
class PVScalar : public PVField {
|
||||
// friend our child class(s) so that it
|
||||
// can call protected methods of other
|
||||
// PVScalar instances.
|
||||
template<typename E> friend class PVScalarValue;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVScalar);
|
||||
/**
|
||||
@@ -394,6 +421,47 @@ public:
|
||||
* @return the interface.
|
||||
*/
|
||||
const ScalarConstPtr getScalar() const ;
|
||||
|
||||
/**
|
||||
* Convert and return the scalar value in the requested type.
|
||||
* Result type is determined from the function template argument
|
||||
* which must be one of the ScalarType enums.
|
||||
* Uses castUnsafe<TO>() for value conversion.
|
||||
@code
|
||||
PVScalar* pv = ...;
|
||||
uint32 val = pv->getAs<pvInt>();
|
||||
@endcode
|
||||
*/
|
||||
template<typename T>
|
||||
inline T getAs() const {
|
||||
T result;
|
||||
this->getAs((void*)&result, (ScalarType)ScalarTypeID<T>::value);
|
||||
return result;
|
||||
}
|
||||
protected:
|
||||
virtual void getAs(void *, ScalarType) const = 0;
|
||||
public:
|
||||
|
||||
/**
|
||||
* Convert and assign the provided value.
|
||||
* The value type is determined from the function template argument
|
||||
* which must be one of the ScalarType enums.
|
||||
* Uses castUnsafe<TO>() for value conversion.
|
||||
@code
|
||||
PVScalar* pv = ...;
|
||||
pv->putFrom<pvInt>((int32)42);
|
||||
@endcode
|
||||
*/
|
||||
template<typename T>
|
||||
inline void putFrom(T val) {
|
||||
this->putFrom((const void*)&val, (ScalarType)ScalarTypeID<T>::value);
|
||||
}
|
||||
protected:
|
||||
virtual void putFrom(const void *, ScalarType) = 0;
|
||||
public:
|
||||
|
||||
virtual void assign(const PVScalar&) = 0;
|
||||
|
||||
protected:
|
||||
PVScalar(ScalarConstPtr const & scalar);
|
||||
};
|
||||
@@ -408,6 +476,9 @@ public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
static const ScalarType typeCode;
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
@@ -442,9 +513,42 @@ public:
|
||||
put(value);
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
inline T1 getAs() const {
|
||||
T1 result(castUnsafe<T1,T>(get()));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
inline void putFrom(T1 val) {
|
||||
put(castUnsafe<T,T1>(val));
|
||||
}
|
||||
|
||||
protected:
|
||||
PVScalarValue(ScalarConstPtr const & scalar)
|
||||
: PVScalar(scalar) {}
|
||||
virtual void getAs(void * result, ScalarType rtype) const
|
||||
{
|
||||
const T src = get();
|
||||
castUnsafeV(1, rtype, result, typeCode, (const void*)&src);
|
||||
}
|
||||
virtual void putFrom(const void *src, ScalarType stype)
|
||||
{
|
||||
T result;
|
||||
castUnsafeV(1, typeCode, (void*)&result, stype, src);
|
||||
put(result);
|
||||
}
|
||||
virtual void assign(const PVScalar& scalar)
|
||||
{
|
||||
if(this==&scalar)
|
||||
return;
|
||||
if(isImmutable())
|
||||
throw std::invalid_argument("Destination is immutable");
|
||||
T result;
|
||||
scalar.getAs((void*)&result, typeCode);
|
||||
put(result);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
@@ -452,7 +556,7 @@ private:
|
||||
/**
|
||||
* typedefs for the various possible scalar types.
|
||||
*/
|
||||
typedef PVScalarValue<uint8> PVBoolean;
|
||||
typedef PVScalarValue<boolean> PVBoolean;
|
||||
typedef PVScalarValue<int8> PVByte;
|
||||
typedef PVScalarValue<int16> PVShort;
|
||||
typedef PVScalarValue<int32> PVInt;
|
||||
@@ -500,7 +604,7 @@ public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PVArray();
|
||||
virtual ~PVArray(){};
|
||||
/**
|
||||
* Set the field to be immutable, i. e. it can no longer be modified.
|
||||
* This is permanent, i.e. once done the field can onot be made mutable.
|
||||
@@ -510,17 +614,17 @@ public:
|
||||
* Get the array length.
|
||||
* @return The length.
|
||||
*/
|
||||
std::size_t getLength() const;
|
||||
virtual std::size_t getLength() const = 0;
|
||||
/**
|
||||
* Set the array length.
|
||||
* @param The length.
|
||||
*/
|
||||
virtual void setLength(std::size_t length);
|
||||
virtual void setLength(std::size_t length) = 0;
|
||||
/**
|
||||
* Get the array capacity.
|
||||
* @return The capacity.
|
||||
*/
|
||||
std::size_t getCapacity() const;
|
||||
virtual std::size_t getCapacity() const = 0;
|
||||
/**
|
||||
* Can the capacity be changed.
|
||||
* @return (false,true) if (can not, can) be changed.
|
||||
@@ -541,9 +645,8 @@ public:
|
||||
|
||||
protected:
|
||||
PVArray(FieldConstPtr const & field);
|
||||
void setCapacityLength(std::size_t capacity,std::size_t length);
|
||||
private:
|
||||
class PVArrayPvt * pImpl;
|
||||
bool capacityMutable;
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
@@ -594,115 +697,62 @@ public:
|
||||
const ScalarArrayConstPtr getScalarArray() const ;
|
||||
|
||||
protected:
|
||||
PVScalarArray(ScalarArrayConstPtr const & scalarArray);
|
||||
private:
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is provided by code that calls get.
|
||||
*/
|
||||
typedef PVArrayData<PVStructurePtr> StructureArrayData;
|
||||
|
||||
/**
|
||||
* Data class for a structureArray
|
||||
*/
|
||||
class PVStructureArray : public PVArray
|
||||
{
|
||||
virtual void _getAsVoid(shared_vector<const void>&) const = 0;
|
||||
virtual void _putFromVoid(const shared_vector<const void>&) = 0;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVStructureArray);
|
||||
typedef PVStructurePtr value_type;
|
||||
typedef PVStructurePtr* pointer;
|
||||
typedef const PVStructurePtr* const_pointer;
|
||||
typedef PVArrayData<PVStructurePtr> ArrayDataType;
|
||||
typedef std::vector<PVStructurePtr> vector;
|
||||
typedef const std::vector<PVStructurePtr> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVStructureArray &reference;
|
||||
typedef const PVStructureArray& const_reference;
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PVStructureArray() {}
|
||||
/**
|
||||
* Set the array capacity.
|
||||
* @param capacity The length.
|
||||
*/
|
||||
virtual void setCapacity(size_t capacity);
|
||||
/**
|
||||
* Set the array length.
|
||||
* @param length The length.
|
||||
*/
|
||||
virtual void setLength(std::size_t length);
|
||||
/**
|
||||
* Get the introspection interface
|
||||
* @return The interface.
|
||||
*/
|
||||
virtual StructureArrayConstPtr getStructureArray() const ;
|
||||
/**
|
||||
* Append new elements to the end of the array.
|
||||
* @param number The number of elements to add.
|
||||
* @return the new length of the array.
|
||||
*/
|
||||
virtual std::size_t append(std::size_t number);
|
||||
/**
|
||||
* Remove elements from the array.
|
||||
* @param offset The offset of the first element to remove.
|
||||
* @param number The number of elements to remove.
|
||||
* @return (false,true) if the elements were removed.
|
||||
*/
|
||||
virtual bool remove(std::size_t offset,std::size_t number);
|
||||
/**
|
||||
* Compress. This removes all null elements from the array.
|
||||
*/
|
||||
virtual void compress();
|
||||
/**
|
||||
* Get array elements
|
||||
* @param offset The offset of the first element,
|
||||
* @param length The number of elements to get.
|
||||
* @param data The place where the data is placed.
|
||||
*/
|
||||
virtual std::size_t get(std::size_t offset, std::size_t length,
|
||||
StructureArrayData &data);
|
||||
/**
|
||||
* Put data into the array.
|
||||
* @param offset The offset of the first element,
|
||||
* @param length The number of elements to get.
|
||||
* @param from The new values to put into the array.
|
||||
* @param fromOffset The offset in from.
|
||||
* @return The number of elements put into the array.
|
||||
*/
|
||||
virtual std::size_t put(std::size_t offset,std::size_t length,
|
||||
const_vector const & from, std::size_t fromOffset);
|
||||
/**
|
||||
* Share data from another source.
|
||||
* @param value The data to share.
|
||||
* @param capacity The capacity of the array.
|
||||
* @param length The length of the array.
|
||||
*/
|
||||
virtual void shareData(
|
||||
shared_vector const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
|
||||
virtual pointer get() { return &((*value.get())[0]); }
|
||||
virtual pointer get() const { return &((*value.get())[0]); }
|
||||
virtual vector const & getVector() {return *value;}
|
||||
virtual shared_vector const & getSharedVector() {return value;}
|
||||
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const;
|
||||
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
|
||||
/**
|
||||
* Fetch the current value and convert to the requested type.
|
||||
*
|
||||
* A copy is made if the requested type does not match
|
||||
* the element type. If the types do match then
|
||||
* no copy is made.
|
||||
*/
|
||||
template<typename T>
|
||||
void
|
||||
getAs(shared_vector<const T>& out) const
|
||||
{
|
||||
shared_vector<const void> temp;
|
||||
_getAsVoid(temp);
|
||||
out = shared_vector_convert<const T>(temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign the given value after conversion.
|
||||
*
|
||||
* A copy and element-wise conversion is performed unless
|
||||
* the element type of the PVScalarArray matches the
|
||||
* type of the provided data.
|
||||
* If the types do match then a new refernce to the provided
|
||||
* data is kept.
|
||||
*
|
||||
* Calls postPut()
|
||||
*/
|
||||
template<typename T>
|
||||
inline void putFrom(const shared_vector<const T>& inp)
|
||||
{
|
||||
shared_vector<const void> temp(static_shared_vector_cast<const void>(inp));
|
||||
_putFromVoid(temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign the given PVScalarArray's value.
|
||||
*
|
||||
* A copy and element-wise conversion is performed unless
|
||||
* the element type of the PVScalarArray matches the
|
||||
* type of the provided data.
|
||||
* If the types do match then a new refernce to the provided
|
||||
* data is kept.
|
||||
*/
|
||||
void assign(PVScalarArray& pv) {
|
||||
shared_vector<const void> temp;
|
||||
pv._getAsVoid(temp);
|
||||
_putFromVoid(temp);
|
||||
}
|
||||
|
||||
protected:
|
||||
PVStructureArray(StructureArrayConstPtr const & structureArray);
|
||||
PVScalarArray(ScalarArrayConstPtr const & scalarArray);
|
||||
private:
|
||||
StructureArrayConstPtr structureArray;
|
||||
shared_vector value;
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
@@ -934,99 +984,328 @@ private:
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// adaptor to allow epics::pvData::shared_vector to hold a reference
|
||||
// to a shared_ptr<std::vector<> >
|
||||
template<typename T>
|
||||
struct shared_ptr_vector_deletor {
|
||||
typedef std::tr1::shared_ptr<std::vector<T> > shared_vector;
|
||||
shared_vector vec;
|
||||
shared_ptr_vector_deletor(const shared_vector& v)
|
||||
:vec(v) {}
|
||||
void operator()(T*){vec.reset();}
|
||||
};
|
||||
|
||||
template<typename T, class Base>
|
||||
class PVVectorStorage : public Base
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
//TODO: full namespace can be removed along with local typedef 'shared_vector'
|
||||
typedef ::epics::pvData::shared_vector<T> svector;
|
||||
typedef ::epics::pvData::shared_vector<const T> const_svector;
|
||||
|
||||
// begin deprecated
|
||||
typedef PVArrayData<T> ArrayDataType;
|
||||
typedef std::vector<T> vector;
|
||||
typedef const std::vector<T> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
// end deprecated
|
||||
|
||||
protected:
|
||||
PVVectorStorage() : Base() {}
|
||||
|
||||
template<typename A>
|
||||
PVVectorStorage(A a) : Base(a) {}
|
||||
public:
|
||||
virtual ~PVVectorStorage(){};
|
||||
|
||||
// Primative array manipulations
|
||||
|
||||
//! Fetch a read-only view of the current array data
|
||||
virtual const_svector view() const = 0;
|
||||
|
||||
/** Exchange our contents for the provided.
|
||||
*
|
||||
@throws std::logic_error for Immutable arrays.
|
||||
*
|
||||
* Callers must ensure that postPut() is called
|
||||
* after the last swap() operation.
|
||||
*
|
||||
* Before you call this directly, consider using
|
||||
* the reuse(), or replace() methods.
|
||||
*/
|
||||
virtual void swap(const_svector& other) = 0;
|
||||
|
||||
//! Discard current contents and replaced with the provided.
|
||||
//! Fails for Immutable arrays
|
||||
//! calls postPut()
|
||||
virtual void replace(const const_svector& next) = 0;
|
||||
|
||||
// Derived operations
|
||||
|
||||
/** Remove and return the current array data
|
||||
* or an unique copy if shared.
|
||||
*
|
||||
* Does @b not (and should not) call postPut()
|
||||
*
|
||||
* The returned shared_vector<T> will
|
||||
* have unique()==true.
|
||||
*/
|
||||
inline svector reuse()
|
||||
{
|
||||
const_svector result;
|
||||
this->swap(result);
|
||||
return thaw(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array elements
|
||||
* @param offset The offset of the first element,
|
||||
* @param length The number of elements to get.
|
||||
* @param data The place where the data is placed.
|
||||
*/
|
||||
std::size_t get(
|
||||
std::size_t offset, std::size_t length, ArrayDataType &data) USAGE_DEPRECATED
|
||||
{
|
||||
const_svector ref = this->view();
|
||||
ref.slice(offset, length);
|
||||
data.data.resize(ref.size());
|
||||
data.offset = 0;
|
||||
std::copy(ref.begin(), ref.end(), data.data.begin());
|
||||
return ref.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy data into the array growing the length as needed.
|
||||
* @param offset The offset of the first element,
|
||||
* @param length The number of elements to get.
|
||||
* @param from The new values to put into the array.
|
||||
* @param fromOffset The offset in from.
|
||||
* @return The number of elements put into the array.
|
||||
* calls postPut()
|
||||
*/
|
||||
std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_pointer from, std::size_t fromOffset) USAGE_DEPRECATED
|
||||
{
|
||||
from += fromOffset;
|
||||
|
||||
svector temp(this->reuse());
|
||||
if(temp.size() < length+offset)
|
||||
temp.resize(length+offset);
|
||||
else
|
||||
temp.make_unique();
|
||||
|
||||
std::copy(from, from + length, temp.begin() + offset);
|
||||
this->replace(freeze(temp));
|
||||
return length;
|
||||
}
|
||||
|
||||
std::size_t put(std::size_t offset,
|
||||
std::size_t length, const_vector &from, std::size_t fromOffset) USAGE_DEPRECATED
|
||||
{ return this->put(offset,length, &from[0], fromOffset); }
|
||||
|
||||
/**
|
||||
* Share data from another source.
|
||||
* @param value The data to share.
|
||||
* @param capacity The capacity of the array.
|
||||
* @param length The length of the array.
|
||||
* Does @b not call postPut()
|
||||
*/
|
||||
void shareData(
|
||||
shared_vector const & value,
|
||||
std::size_t capacity,
|
||||
std::size_t length) USAGE_DEPRECATED
|
||||
{
|
||||
vector& vref = *value.get();
|
||||
typename svector::shared_pointer_type p(&vref[0],
|
||||
detail::shared_ptr_vector_deletor<T>(value));
|
||||
const_svector temp(p, 0, std::min(length, vref.size()));
|
||||
this->swap(temp);
|
||||
}
|
||||
|
||||
pointer get() const USAGE_DEPRECATED {
|
||||
// evil unsafe cast!
|
||||
return (pointer)this->view().data();
|
||||
}
|
||||
|
||||
vector const & getVector() USAGE_ERROR("No longer implemented. Replace with view()");
|
||||
shared_vector const & getSharedVector() USAGE_ERROR("No longer implemented. Replace with view()");
|
||||
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
class PVValueArray : public PVScalarArray {
|
||||
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;
|
||||
|
||||
//TODO: full namespace can be removed along with local typedef 'shared_vector'
|
||||
typedef ::epics::pvData::shared_vector<T> svector;
|
||||
typedef ::epics::pvData::shared_vector<const T> const_svector;
|
||||
|
||||
// begin deprecated
|
||||
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;
|
||||
// end deprecated
|
||||
|
||||
static const ScalarType typeCode;
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PVValueArray() {}
|
||||
/**
|
||||
* Get array elements
|
||||
* @param offset The offset of the first element,
|
||||
* @param length The number of elements to get.
|
||||
* @param data The place where the data is placed.
|
||||
*/
|
||||
virtual std::size_t get(
|
||||
std::size_t offset, std::size_t length, ArrayDataType &data) = 0;
|
||||
/**
|
||||
* Put data into the array.
|
||||
* @param offset The offset of the first element,
|
||||
* @param length The number of elements to get.
|
||||
* @param from The new values to put into the array.
|
||||
* @param fromOffset The offset in from.
|
||||
* @return The number of elements put into the array.
|
||||
*/
|
||||
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);
|
||||
/**
|
||||
* Share data from another source.
|
||||
* @param value The data to share.
|
||||
* @param capacity The capacity of the array.
|
||||
* @param length The length of the array.
|
||||
*/
|
||||
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
|
||||
{
|
||||
const_svector v(this->view());
|
||||
typename const_svector::const_iterator it(v.begin()),
|
||||
end(v.end());
|
||||
o << '[';
|
||||
std::size_t len = getLength();
|
||||
bool first = true;
|
||||
for (std::size_t i = 0; i < len; i++)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
o << ',';
|
||||
dumpValue(o, i);
|
||||
}
|
||||
if(it!=end) {
|
||||
o << print_cast(*it++);
|
||||
for(; it!=end; ++it)
|
||||
o << ',' << print_cast(*it);
|
||||
|
||||
}
|
||||
return o << ']';
|
||||
}
|
||||
|
||||
std::ostream& dumpValue(std::ostream& o, size_t index) const
|
||||
{
|
||||
return o << *(get() + index);
|
||||
return o << print_cast(this->view().at(index));
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void _getAsVoid(epics::pvData::shared_vector<const void>& out) const
|
||||
{
|
||||
out = static_shared_vector_cast<const void>(this->view());
|
||||
}
|
||||
|
||||
virtual void _putFromVoid(const epics::pvData::shared_vector<const void>& in)
|
||||
{
|
||||
// TODO: try to re-use storage
|
||||
replace(shared_vector_convert<const T>(in));
|
||||
}
|
||||
|
||||
PVValueArray(ScalarArrayConstPtr const & scalar)
|
||||
: PVScalarArray(scalar) {}
|
||||
: base_t(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); }
|
||||
/**
|
||||
* This is provided by code that calls get.
|
||||
*/
|
||||
typedef PVArrayData<PVStructurePtr> StructureArrayData;
|
||||
|
||||
/**
|
||||
* Data class for a structureArray
|
||||
*/
|
||||
template<>
|
||||
class PVValueArray<PVStructurePtr> : public detail::PVVectorStorage<PVStructurePtr,PVArray>
|
||||
{
|
||||
typedef detail::PVVectorStorage<PVStructurePtr,PVArray> base_t;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVStructureArray);
|
||||
typedef PVStructurePtr value_type;
|
||||
typedef PVStructurePtr* pointer;
|
||||
typedef const PVStructurePtr* const_pointer;
|
||||
typedef PVArrayData<PVStructurePtr> ArrayDataType;
|
||||
typedef std::vector<PVStructurePtr> vector;
|
||||
typedef const std::vector<PVStructurePtr> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVStructureArray &reference;
|
||||
typedef const PVStructureArray& const_reference;
|
||||
|
||||
//TODO: full namespace can be removed along with local typedef 'shared_vector'
|
||||
typedef ::epics::pvData::shared_vector<PVStructurePtr> svector;
|
||||
typedef ::epics::pvData::shared_vector<const PVStructurePtr> const_svector;
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PVValueArray() {}
|
||||
|
||||
virtual size_t getLength() const {return value.size();}
|
||||
virtual size_t getCapacity() const {return value.capacity();}
|
||||
|
||||
/**
|
||||
* Set the array capacity.
|
||||
* @param capacity The length.
|
||||
*/
|
||||
virtual void setCapacity(size_t capacity);
|
||||
/**
|
||||
* Set the array length.
|
||||
* @param length The length.
|
||||
*/
|
||||
virtual void setLength(std::size_t length);
|
||||
|
||||
/**
|
||||
* Get the introspection interface
|
||||
* @return The interface.
|
||||
*/
|
||||
StructureArrayConstPtr getStructureArray() const {return structureArray;}
|
||||
/**
|
||||
* Append new elements to the end of the array.
|
||||
* @param number The number of elements to add.
|
||||
* @return the new length of the array.
|
||||
*/
|
||||
virtual std::size_t append(std::size_t number);
|
||||
/**
|
||||
* Remove elements from the array.
|
||||
* @param offset The offset of the first element to remove.
|
||||
* @param number The number of elements to remove.
|
||||
* @return (false,true) if the elements were removed.
|
||||
*/
|
||||
virtual bool remove(std::size_t offset,std::size_t number);
|
||||
/**
|
||||
* Compress. This removes all null elements from the array.
|
||||
*/
|
||||
virtual void compress();
|
||||
|
||||
virtual const_svector view() const { return value; }
|
||||
virtual void swap(const_svector &other);
|
||||
virtual void replace(const const_svector &other) {
|
||||
value = other;
|
||||
PVField::postPut();
|
||||
}
|
||||
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
|
||||
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const;
|
||||
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
|
||||
|
||||
protected:
|
||||
PVValueArray(StructureArrayConstPtr const & structureArray)
|
||||
:base_t(structureArray)
|
||||
,structureArray(structureArray)
|
||||
{}
|
||||
private:
|
||||
StructureArrayConstPtr structureArray;
|
||||
const_svector value;
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
/**
|
||||
* Definitions for the various scalarArray types.
|
||||
*/
|
||||
typedef PVArrayData<uint8> BooleanArrayData;
|
||||
typedef PVValueArray<uint8> PVBooleanArray;
|
||||
typedef PVArrayData<boolean> BooleanArrayData;
|
||||
typedef PVValueArray<boolean> PVBooleanArray;
|
||||
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;
|
||||
|
||||
typedef PVArrayData<int8> ByteArrayData;
|
||||
@@ -1171,6 +1450,9 @@ private:
|
||||
*/
|
||||
|
||||
extern PVDataCreatePtr getPVDataCreate();
|
||||
|
||||
|
||||
#undef USAGE_DEPRECATED
|
||||
#undef USAGE_ERROR
|
||||
|
||||
}}
|
||||
#endif /* PVDATA_H */
|
||||
|
||||
@@ -191,6 +191,9 @@ namespace ScalarTypeFunc {
|
||||
* @param scalarType The type.
|
||||
*/
|
||||
void toString(StringBuilder builder,ScalarType scalarType);
|
||||
|
||||
//! gives sizeof(T) where T depends on the scalar type id.
|
||||
size_t elementSize(ScalarType id);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -439,7 +442,7 @@ public:
|
||||
* @param fieldIndex The index of the desired field.
|
||||
* @return The fieldName.
|
||||
*/
|
||||
String getFieldName(std::size_t fieldIndex){return fieldNames[fieldIndex];}
|
||||
String getFieldName(std::size_t fieldIndex) const {return fieldNames[fieldIndex];}
|
||||
/**
|
||||
* Convert the structure to a string and add it to builder.
|
||||
* @param builder The string builder.
|
||||
@@ -555,5 +558,46 @@ private:
|
||||
*/
|
||||
extern FieldCreatePtr getFieldCreate();
|
||||
|
||||
/** Define a compile time mapping from
|
||||
* type to enum value.
|
||||
@code
|
||||
ScalarType code = (ScalarType)ScalarTypeID<int8>::value;
|
||||
assert(code==pvByte);
|
||||
@endcode
|
||||
*
|
||||
* For unspecified types this evaluates to an invalid ScalarType
|
||||
* value (eg -1).
|
||||
*/
|
||||
template<typename T>
|
||||
struct ScalarTypeID { enum {value=-1}; };
|
||||
|
||||
/**
|
||||
* Static mapping from ScalarType enum to value type.
|
||||
@code
|
||||
typename ScalarTypeTraits<pvByte>::type value = 4;
|
||||
@endcode
|
||||
*/
|
||||
template<ScalarType ID>
|
||||
struct ScalarTypeTraits {};
|
||||
|
||||
#define OP(ENUM, TYPE) \
|
||||
template<> struct ScalarTypeTraits<ENUM> {typedef TYPE type;}; \
|
||||
template<> struct ScalarTypeID<TYPE> { enum {value=ENUM}; }; \
|
||||
template<> struct ScalarTypeID<const TYPE> { enum {value=ENUM}; };
|
||||
|
||||
OP(pvBoolean, boolean)
|
||||
OP(pvByte, int8)
|
||||
OP(pvShort, int16)
|
||||
OP(pvInt, int32)
|
||||
OP(pvLong, int64)
|
||||
OP(pvUByte, uint8)
|
||||
OP(pvUShort, uint16)
|
||||
OP(pvUInt, uint32)
|
||||
OP(pvULong, uint64)
|
||||
OP(pvFloat, float)
|
||||
OP(pvDouble, double)
|
||||
OP(pvString, String)
|
||||
#undef OP
|
||||
|
||||
}}
|
||||
#endif /* PVINTROSPECT_H */
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
(_WRS_VXWORKS_MAJOR+0 <= 6) && (_WRS_VXWORKS_MINOR+0 < 9)
|
||||
typedef int intptr_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
#ifndef INT64_MAX
|
||||
#define INT64_MAX (0x7fffffffffffffffLL)
|
||||
#define UINT64_MAX (0xffffffffffffffffLL)
|
||||
#endif
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
@@ -32,6 +34,14 @@ typedef unsigned int uintptr_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
namespace detail {
|
||||
// Pick either type If or type Else to not be Cond
|
||||
template<typename Cond, typename If, typename Else>
|
||||
struct pick_type { typedef If type; };
|
||||
template<typename Cond, typename Else>
|
||||
struct pick_type<Cond,Cond,Else> { typedef Else type; };
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a set of typdefs used by pvData.
|
||||
*/
|
||||
@@ -39,7 +49,9 @@ namespace epics { namespace pvData {
|
||||
/**
|
||||
* boolean, i.e. can only have the values {@code false} or {@code true}
|
||||
*/
|
||||
typedef uint8_t boolean;
|
||||
typedef detail::pick_type<int8_t, signed char,
|
||||
detail::pick_type<uint8_t, char, unsigned char>::type
|
||||
>::type boolean;
|
||||
/**
|
||||
* A 8 bit signed integer
|
||||
*/
|
||||
|
||||
@@ -2,45 +2,48 @@ TOP=../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PROD_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testThread
|
||||
testThread_SRCS += testThread.cpp
|
||||
testThread_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testTimer
|
||||
testTimer_SRCS += testTimer.cpp
|
||||
testTimer_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testBitSet
|
||||
testBitSet_SRCS += testBitSet.cpp
|
||||
testBitSet_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testByteOrder
|
||||
testByteOrder_SRCS += testByteOrder.cpp
|
||||
testByteOrder_LIBS += Com
|
||||
|
||||
PROD_HOST += testByteBuffer
|
||||
testByteBuffer_SRCS += testByteBuffer.cpp
|
||||
testByteBuffer_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testBaseException
|
||||
testBaseException_SRCS += testBaseException.cpp
|
||||
testBaseException_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testSerialization
|
||||
TESTPROD += testSerialization
|
||||
testSerialization_SRCS += testSerialization.cpp
|
||||
testSerialization_LIBS += pvData Com
|
||||
TESTS += testSerialization
|
||||
|
||||
PROD_HOST += testTimeStamp
|
||||
testTimeStamp_SRCS += testTimeStamp.cpp
|
||||
testTimeStamp_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testQueue
|
||||
testQueue_SRCS += testQueue.cpp
|
||||
testQueue_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testMessageQueue
|
||||
testMessageQueue_SRCS += testMessageQueue.cpp
|
||||
testMessageQueue_LIBS += pvData Com
|
||||
|
||||
TESTPROD += testTypeCast
|
||||
testTypeCast_SRCS += testTypeCast.cpp
|
||||
TESTS += testTypeCast
|
||||
|
||||
TESTPROD += testSharedVector
|
||||
testSharedVector_SRCS += testSharedVector.cpp
|
||||
TESTS += testSharedVector
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
#include <dbDefs.h> // for NELEMENTS
|
||||
|
||||
#include <epicsExit.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
@@ -45,6 +47,8 @@
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace {
|
||||
|
||||
static SerializableControl* flusher;
|
||||
static DeserializableControl* control;
|
||||
static ByteBuffer* buffer;
|
||||
@@ -122,14 +126,23 @@ void serializationTest(PVFieldPtr const & field) {
|
||||
deserializedField->deserialize(buffer, control);
|
||||
|
||||
// must equal
|
||||
bool isEqual = getConvert()->equals(*field,*deserializedField);
|
||||
assert(isEqual);
|
||||
if(*field==*deserializedField)
|
||||
testPass("Serialization round trip OK");
|
||||
else {
|
||||
testFail("Serialization round trip did not match!");
|
||||
std::string buf;
|
||||
field->toString(&buf);
|
||||
testDiag("Expected: %s", buf.c_str());
|
||||
buf.clear();
|
||||
deserializedField->toString(&buf);
|
||||
testDiag("Found: %s", buf.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void testEquals(std::ostream& ofile) {
|
||||
ofile<<"Testing equals...\n";
|
||||
void testEquals() {
|
||||
testDiag("Testing equals...");
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
assert(factory.get()!=NULL);
|
||||
testOk1(factory.get()!=NULL);
|
||||
|
||||
// be sure all is covered
|
||||
for (int i = pvBoolean; i < pvString; i++)
|
||||
@@ -138,32 +151,63 @@ void testEquals(std::ostream& ofile) {
|
||||
|
||||
PVScalarPtr scalar1 = factory->createPVScalar(scalarType);
|
||||
PVScalarPtr scalar2 = factory->createPVScalar(scalarType);
|
||||
assert((*scalar1)==(*scalar2));
|
||||
testOk1((*scalar1)==(*scalar2));
|
||||
|
||||
PVScalarArrayPtr array1 = factory->createPVScalarArray(scalarType);
|
||||
PVScalarArrayPtr array2 = factory->createPVScalarArray(scalarType);
|
||||
assert((*array1)==(*array2));
|
||||
testOk1((*array1)==(*array2));
|
||||
}
|
||||
|
||||
// and a structure
|
||||
PVStructurePtr structure1 = factory->createPVStructure(getStandardField()->timeStamp());
|
||||
PVStructurePtr structure2 = factory->createPVStructure(getStandardField()->timeStamp());
|
||||
assert((*structure1)==(*structure2));
|
||||
testOk1((*structure1)==(*structure2));
|
||||
|
||||
// and a structure array
|
||||
PVStructureArrayPtr structureArray1 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure1->getStructure()));
|
||||
PVStructureArrayPtr structureArray2 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure2->getStructure()));
|
||||
assert((*structureArray1)==(*structureArray2));
|
||||
|
||||
ofile<<"!!! PASSED\n\n";
|
||||
testOk1((*structureArray1)==(*structureArray2));
|
||||
}
|
||||
|
||||
void testScalar(std::ostream& ofile) {
|
||||
ofile<<"Testing scalars...\n";
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
assert(factory.get()!=NULL);
|
||||
template<typename PVT>
|
||||
void testScalarType()
|
||||
{
|
||||
typedef typename PVT::value_type value_type;
|
||||
|
||||
ofile<<"\tPVBoolean\n";
|
||||
testDiag("type %s", ScalarTypeFunc::name(PVT::typeCode));
|
||||
|
||||
typename PVT::shared_pointer pv = std::tr1::static_pointer_cast<PVT>(getPVDataCreate()->createPVScalar(PVT::typeCode));
|
||||
|
||||
pv->put(0);
|
||||
serializationTest(pv);
|
||||
pv->put(42);
|
||||
serializationTest(pv);
|
||||
pv->put(std::numeric_limits<value_type>::max()-1);
|
||||
serializationTest(pv);
|
||||
pv->put(std::numeric_limits<value_type>::max());
|
||||
serializationTest(pv);
|
||||
|
||||
if(std::numeric_limits<value_type>::min()!=0) {
|
||||
pv->put(-42);
|
||||
serializationTest(pv);
|
||||
pv->put(std::numeric_limits<value_type>::min()+1);
|
||||
serializationTest(pv);
|
||||
pv->put(std::numeric_limits<value_type>::min());
|
||||
serializationTest(pv);
|
||||
}
|
||||
|
||||
if(std::numeric_limits<value_type>::has_infinity) {
|
||||
pv->put(std::numeric_limits<value_type>::infinity());
|
||||
serializationTest(pv);
|
||||
}
|
||||
}
|
||||
|
||||
void testScalar() {
|
||||
testDiag("Testing scalars...");
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
testOk1(factory.get()!=NULL);
|
||||
|
||||
testDiag("type %s", ScalarTypeFunc::name(pvBoolean));
|
||||
PVBooleanPtr pvBoolean =
|
||||
std::tr1::static_pointer_cast<PVBoolean>(factory->createPVScalar(epics::pvData::pvBoolean));
|
||||
pvBoolean->put(false);
|
||||
@@ -171,196 +215,19 @@ void testScalar(std::ostream& ofile) {
|
||||
pvBoolean->put(true);
|
||||
serializationTest(pvBoolean);
|
||||
|
||||
ofile<<"\tPVByte\n";
|
||||
PVBytePtr pvByte =
|
||||
std::tr1::static_pointer_cast<PVByte>(factory->createPVScalar(epics::pvData::pvByte));
|
||||
pvByte->put(0);
|
||||
serializationTest(pvByte);
|
||||
pvByte->put(12);
|
||||
serializationTest(pvByte);
|
||||
pvByte->put(BYTE_MAX_VALUE);
|
||||
serializationTest(pvByte);
|
||||
pvByte->put(BYTE_MIN_VALUE);
|
||||
serializationTest(pvByte);
|
||||
|
||||
ofile<<"\tPVShort\n";
|
||||
PVShortPtr pvShort =
|
||||
std::tr1::static_pointer_cast<PVShort>(factory->createPVScalar(epics::pvData::pvShort));
|
||||
pvShort->put(0);
|
||||
serializationTest(pvShort);
|
||||
pvShort->put(123);
|
||||
serializationTest(pvShort);
|
||||
pvShort->put(BYTE_MAX_VALUE);
|
||||
serializationTest(pvShort);
|
||||
pvShort->put(BYTE_MIN_VALUE);
|
||||
serializationTest(pvShort);
|
||||
pvShort->put(SHORT_MAX_VALUE);
|
||||
serializationTest(pvShort);
|
||||
pvShort->put(SHORT_MIN_VALUE);
|
||||
serializationTest(pvShort);
|
||||
|
||||
ofile<<"\tPVInt\n";
|
||||
PVIntPtr pvInt =
|
||||
std::tr1::static_pointer_cast<PVInt>(factory->createPVScalar(epics::pvData::pvInt));
|
||||
pvInt->put(0);
|
||||
serializationTest(pvInt);
|
||||
pvInt->put(123456);
|
||||
serializationTest(pvInt);
|
||||
pvInt->put(BYTE_MAX_VALUE);
|
||||
serializationTest(pvInt);
|
||||
pvInt->put(BYTE_MIN_VALUE);
|
||||
serializationTest(pvInt);
|
||||
pvInt->put(SHORT_MAX_VALUE);
|
||||
serializationTest(pvInt);
|
||||
pvInt->put(SHORT_MIN_VALUE);
|
||||
serializationTest(pvInt);
|
||||
pvInt->put(INT_MAX_VALUE);
|
||||
serializationTest(pvInt);
|
||||
pvInt->put(INT_MIN_VALUE);
|
||||
serializationTest(pvInt);
|
||||
|
||||
ofile<<"\tPVLong\n";
|
||||
PVLongPtr pvLong =
|
||||
std::tr1::static_pointer_cast<PVLong>(factory->createPVScalar(epics::pvData::pvLong));
|
||||
pvLong->put(0);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(12345678901LL);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(BYTE_MAX_VALUE);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(BYTE_MIN_VALUE);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(SHORT_MAX_VALUE);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(SHORT_MIN_VALUE);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(INT_MAX_VALUE);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(INT_MIN_VALUE);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(LONG_MAX_VALUE);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(LONG_MIN_VALUE);
|
||||
serializationTest(pvLong);
|
||||
testScalarType<PVByte>();
|
||||
testScalarType<PVUByte>();
|
||||
testScalarType<PVShort>();
|
||||
testScalarType<PVUShort>();
|
||||
testScalarType<PVInt>();
|
||||
testScalarType<PVUInt>();
|
||||
testScalarType<PVLong>();
|
||||
testScalarType<PVULong>();
|
||||
testScalarType<PVFloat>();
|
||||
testScalarType<PVDouble>();
|
||||
|
||||
|
||||
ofile<<"\tPVUByte\n";
|
||||
PVUBytePtr pvUByte =
|
||||
std::tr1::static_pointer_cast<PVUByte>(factory->createPVScalar(epics::pvData::pvUByte));
|
||||
pvUByte->put(0);
|
||||
serializationTest(pvUByte);
|
||||
pvUByte->put(12);
|
||||
serializationTest(pvUByte);
|
||||
pvUByte->put(UBYTE_MAX_VALUE);
|
||||
serializationTest(pvUByte);
|
||||
pvUByte->put(BYTE_MAX_VALUE);
|
||||
serializationTest(pvUByte);
|
||||
pvUByte->put(BYTE_MIN_VALUE);
|
||||
serializationTest(pvUByte);
|
||||
|
||||
ofile<<"\tPVUShort\n";
|
||||
PVUShortPtr pvUShort =
|
||||
std::tr1::static_pointer_cast<PVUShort>(factory->createPVScalar(epics::pvData::pvUShort));
|
||||
pvUShort->put(0);
|
||||
serializationTest(pvUShort);
|
||||
pvUShort->put(1234);
|
||||
serializationTest(pvUShort);
|
||||
pvUShort->put(BYTE_MAX_VALUE);
|
||||
serializationTest(pvUShort);
|
||||
pvUShort->put(BYTE_MIN_VALUE);
|
||||
serializationTest(pvUShort);
|
||||
pvUShort->put(UBYTE_MAX_VALUE);
|
||||
serializationTest(pvUShort);
|
||||
pvUShort->put(SHORT_MAX_VALUE);
|
||||
serializationTest(pvUShort);
|
||||
pvUShort->put(SHORT_MIN_VALUE);
|
||||
serializationTest(pvUShort);
|
||||
pvUShort->put(USHORT_MAX_VALUE);
|
||||
serializationTest(pvUShort);
|
||||
|
||||
ofile<<"\tPVInt\n";
|
||||
PVIntPtr pvUInt =
|
||||
std::tr1::static_pointer_cast<PVInt>(factory->createPVScalar(epics::pvData::pvUInt));
|
||||
pvUInt->put(0);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(123456);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(BYTE_MAX_VALUE);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(BYTE_MIN_VALUE);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(UBYTE_MAX_VALUE);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(SHORT_MAX_VALUE);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(SHORT_MIN_VALUE);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(USHORT_MAX_VALUE);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(INT_MAX_VALUE);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(INT_MIN_VALUE);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(UINT_MAX_VALUE);
|
||||
serializationTest(pvUInt);
|
||||
|
||||
ofile<<"\tPVLong\n";
|
||||
PVLongPtr pvULong =
|
||||
std::tr1::static_pointer_cast<PVLong>(factory->createPVScalar(epics::pvData::pvULong));
|
||||
pvULong->put(0);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(12345678901LL);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(BYTE_MAX_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(BYTE_MIN_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(UBYTE_MAX_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(SHORT_MAX_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(SHORT_MIN_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(USHORT_MAX_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(INT_MAX_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(INT_MIN_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(UINT_MAX_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(LONG_MAX_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(LONG_MIN_VALUE);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(ULONG_MAX_VALUE);
|
||||
serializationTest(pvULong);
|
||||
|
||||
ofile<<"\tPVFloat\n";
|
||||
PVFloatPtr pvFloat =
|
||||
std::tr1::static_pointer_cast<PVFloat>(factory->createPVScalar(epics::pvData::pvFloat));
|
||||
pvFloat->put(0);
|
||||
serializationTest(pvFloat);
|
||||
pvFloat->put(12.345);
|
||||
serializationTest(pvFloat);
|
||||
pvFloat->put(FLOAT_MAX_VALUE);
|
||||
serializationTest(pvFloat);
|
||||
pvFloat->put(FLOAT_MIN_VALUE);
|
||||
serializationTest(pvFloat);
|
||||
|
||||
ofile<<"\tPVDouble\n";
|
||||
PVDoublePtr pvDouble =
|
||||
std::tr1::static_pointer_cast<PVDouble>(factory->createPVScalar(epics::pvData::pvDouble));
|
||||
pvDouble->put(0);
|
||||
serializationTest(pvDouble);
|
||||
pvDouble->put(12.345);
|
||||
serializationTest(pvDouble);
|
||||
pvDouble->put(DOUBLE_MAX_VALUE);
|
||||
serializationTest(pvDouble);
|
||||
pvDouble->put(DOUBLE_MIN_VALUE);
|
||||
serializationTest(pvDouble);
|
||||
|
||||
ofile<<"\tPVString\n";
|
||||
testDiag("type %s", ScalarTypeFunc::name(pvString));
|
||||
PVStringPtr pvString =
|
||||
std::tr1::static_pointer_cast<PVString>(factory->createPVScalar(epics::pvData::pvString));
|
||||
pvString->put("");
|
||||
@@ -377,167 +244,88 @@ void testScalar(std::ostream& ofile) {
|
||||
// huge string test
|
||||
pvString->put(String(10000, 'a'));
|
||||
serializationTest(pvString);
|
||||
|
||||
// TODO unsigned test
|
||||
|
||||
ofile<<"!!! PASSED\n\n";
|
||||
}
|
||||
|
||||
void testArray(std::ostream& ofile) {
|
||||
ofile<<"Testing arrays...\n";
|
||||
template<typename PVT>
|
||||
void testArrayType(const typename PVT::value_type* rdata, size_t len)
|
||||
{
|
||||
typedef typename PVT::value_type value_type;
|
||||
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
assert(factory.get()!=NULL);
|
||||
typename PVT::svector empty(0), data(len);
|
||||
|
||||
ofile<<"\tPVBooleanArray\n";
|
||||
//bool boolEmpty[] = { false };
|
||||
//bool bv[] = { false, true, false, true, true };
|
||||
PVBooleanArrayPtr pvBoolean =
|
||||
std::tr1::static_pointer_cast<PVBooleanArray>(factory->createPVScalarArray(epics::pvData::pvBoolean));
|
||||
//pvBoolean->put(0, 0, boolEmpty, 0);
|
||||
serializationTest(pvBoolean);
|
||||
//pvBoolean->put(0, 5, bv, 0);
|
||||
serializationTest(pvBoolean);
|
||||
std::copy(rdata, rdata+len, data.begin());
|
||||
|
||||
ofile<<"\tPVByteArray\n";
|
||||
int8 byteEmpty[] = { 0 };
|
||||
int8 byv[] = { 0, 1, 2, -1, BYTE_MAX_VALUE, BYTE_MAX_VALUE-1,
|
||||
BYTE_MIN_VALUE+1, BYTE_MIN_VALUE };
|
||||
PVByteArrayPtr pvByte =
|
||||
std::tr1::static_pointer_cast<PVByteArray>(factory->createPVScalarArray(epics::pvData::pvByte));
|
||||
pvByte->put(0, 0, byteEmpty, 0);
|
||||
serializationTest(pvByte);
|
||||
pvByte->put(0, 8, byv, 0);
|
||||
serializationTest(pvByte);
|
||||
testDiag("type %s", ScalarTypeFunc::name(PVT::typeCode));
|
||||
|
||||
ofile<<"\tPVShortArray\n";
|
||||
int16 shortEmpty[] = { 0 };
|
||||
int16 sv[] = { 0, 1, 2, -1, SHORT_MAX_VALUE, SHORT_MAX_VALUE-1,
|
||||
SHORT_MIN_VALUE+1, SHORT_MIN_VALUE };
|
||||
PVShortArrayPtr pvShort =
|
||||
std::tr1::static_pointer_cast<PVShortArray>(factory->createPVScalarArray(epics::pvData::pvShort));
|
||||
pvShort->put(0, 0, shortEmpty, 0);
|
||||
serializationTest(pvShort);
|
||||
pvShort->put(0, 8, sv, 0);
|
||||
serializationTest(pvShort);
|
||||
typename PVT::shared_pointer pv = std::tr1::static_pointer_cast<PVT>(getPVDataCreate()->createPVScalarArray(PVT::typeCode));
|
||||
|
||||
ofile<<"\tPVIntArray\n";
|
||||
int32 intEmpty[] = { 0 };
|
||||
int32 iv[] = { 0, 1, 2, -1, INT_MAX_VALUE, INT_MAX_VALUE-1,
|
||||
INT_MIN_VALUE+1, INT_MIN_VALUE };
|
||||
PVIntArrayPtr pvInt =
|
||||
std::tr1::static_pointer_cast<PVIntArray>(factory->createPVScalarArray(epics::pvData::pvInt));
|
||||
pvInt->put(0, 0, intEmpty, 0);
|
||||
serializationTest(pvInt);
|
||||
pvInt->put(0, 8, iv, 0);
|
||||
serializationTest(pvInt);
|
||||
|
||||
ofile<<"\tPVLongArray\n";
|
||||
int64 longEmpty[] = { 0 };
|
||||
int64 lv[] = { 0, 1, 2, -1, LONG_MAX_VALUE, LONG_MAX_VALUE-1,
|
||||
LONG_MIN_VALUE+1, LONG_MIN_VALUE };
|
||||
PVLongArrayPtr pvLong =
|
||||
std::tr1::static_pointer_cast<PVLongArray>(factory->createPVScalarArray(epics::pvData::pvLong));
|
||||
pvLong->put(0, 0, longEmpty, 0);
|
||||
serializationTest(pvLong);
|
||||
pvLong->put(0, 8, lv, 0);
|
||||
serializationTest(pvLong);
|
||||
|
||||
ofile<<"\tPVUByteArray\n";
|
||||
uint8 ubyteEmpty[] = { 0 };
|
||||
uint8 ubyv[] = { 0, 1, 2, -1, BYTE_MAX_VALUE, BYTE_MAX_VALUE-1,
|
||||
BYTE_MIN_VALUE+1, BYTE_MIN_VALUE, UBYTE_MAX_VALUE };
|
||||
PVUByteArrayPtr pvUByte =
|
||||
std::tr1::static_pointer_cast<PVUByteArray>(factory->createPVScalarArray(epics::pvData::pvUByte));
|
||||
pvUByte->put(0, 0, ubyteEmpty, 0);
|
||||
serializationTest(pvUByte);
|
||||
pvUByte->put(0, 9, ubyv, 0);
|
||||
serializationTest(pvUByte);
|
||||
|
||||
ofile<<"\tPVUShortArray\n";
|
||||
uint16 ushortEmpty[] = { 0 };
|
||||
uint16 usv[] = { 0, 1, 2, -1, SHORT_MAX_VALUE, SHORT_MAX_VALUE-1,
|
||||
SHORT_MIN_VALUE+1, SHORT_MIN_VALUE, USHORT_MAX_VALUE };
|
||||
PVUShortArrayPtr pvUShort =
|
||||
std::tr1::static_pointer_cast<PVUShortArray>(factory->createPVScalarArray(epics::pvData::pvUShort));
|
||||
pvUShort->put(0, 0, ushortEmpty, 0);
|
||||
serializationTest(pvUShort);
|
||||
pvUShort->put(0, 8, usv, 0);
|
||||
serializationTest(pvUShort);
|
||||
|
||||
ofile<<"\tPVUIntArray\n";
|
||||
uint32 uintEmpty[] = { 0 };
|
||||
uint32 uiv[] = { 0, 1, 2, -1, INT_MAX_VALUE, INT_MAX_VALUE-1,
|
||||
INT_MIN_VALUE+1, INT_MIN_VALUE, UINT_MAX_VALUE };
|
||||
PVUIntArrayPtr pvUInt =
|
||||
std::tr1::static_pointer_cast<PVUIntArray>(factory->createPVScalarArray(epics::pvData::pvUInt));
|
||||
pvUInt->put(0, 0, uintEmpty, 0);
|
||||
serializationTest(pvUInt);
|
||||
pvUInt->put(0, 9, uiv, 0);
|
||||
serializationTest(pvUInt);
|
||||
|
||||
ofile<<"\tPVULongArray\n";
|
||||
uint64 ulongEmpty[] = { 0 };
|
||||
uint64 ulv[] = { 0, 1, 2, -1, LONG_MAX_VALUE, LONG_MAX_VALUE-1,
|
||||
LONG_MIN_VALUE+1, LONG_MIN_VALUE, ULONG_MAX_VALUE };
|
||||
PVULongArrayPtr pvULong =
|
||||
std::tr1::static_pointer_cast<PVULongArray>(factory->createPVScalarArray(epics::pvData::pvULong));
|
||||
pvULong->put(0, 0, ulongEmpty, 0);
|
||||
serializationTest(pvULong);
|
||||
pvULong->put(0, 9, ulv, 0);
|
||||
serializationTest(pvULong);
|
||||
|
||||
ofile<<"\tPVFloatArray\n";
|
||||
float floatEmpty[] = { (float)0.0 };
|
||||
float fv[] = { (float)0.0, (float)1.1, (float)2.3, (float)-1.4,
|
||||
FLOAT_MAX_VALUE, FLOAT_MAX_VALUE-(float)123456.789, FLOAT_MIN_VALUE
|
||||
+(float)1.1, FLOAT_MIN_VALUE };
|
||||
PVFloatArrayPtr pvFloat =
|
||||
std::tr1::static_pointer_cast<PVFloatArray>(factory->createPVScalarArray(epics::pvData::pvFloat));
|
||||
pvFloat->put(0, 0, floatEmpty, 0);
|
||||
serializationTest(pvFloat);
|
||||
pvFloat->put(0, 8, fv, 0);
|
||||
serializationTest(pvFloat);
|
||||
|
||||
ofile<<"\tPVDoubleArray\n";
|
||||
double doubleEmpty[] = { (double)0.0 };
|
||||
double dv[] = { (double)0.0, (double)1.1, (double)2.3, (double)-1.4,
|
||||
DOUBLE_MAX_VALUE, DOUBLE_MAX_VALUE-(double)123456.789,
|
||||
DOUBLE_MIN_VALUE+(double)1.1, DOUBLE_MIN_VALUE };
|
||||
PVDoubleArrayPtr pvDouble =
|
||||
std::tr1::static_pointer_cast<PVDoubleArray>(factory->createPVScalarArray(epics::pvData::pvDouble));
|
||||
pvDouble->put(0, 0, doubleEmpty, 0);
|
||||
serializationTest(pvDouble);
|
||||
pvDouble->put(0, 8, dv, 0);
|
||||
serializationTest(pvDouble);
|
||||
|
||||
ofile<<"\tPVStringArray\n";
|
||||
String stringEmpty[] = { "" };
|
||||
String
|
||||
strv[] =
|
||||
{
|
||||
"",
|
||||
"a",
|
||||
"a b",
|
||||
" ",
|
||||
"test",
|
||||
"smile",
|
||||
"this is a little longer string... maybe a little but longer... this makes test better",
|
||||
String(10000, 'b') };
|
||||
PVStringArrayPtr pvString =
|
||||
std::tr1::static_pointer_cast<PVStringArray>(factory->createPVScalarArray(epics::pvData::pvString));
|
||||
pvString->put(0, 0, stringEmpty, 0);
|
||||
serializationTest(pvString);
|
||||
pvString->put(0, 8, strv, 0);
|
||||
serializationTest(pvString);
|
||||
|
||||
ofile<<"!!! PASSED\n\n";
|
||||
pv->replace(freeze(empty));
|
||||
serializationTest(pv);
|
||||
pv->replace(freeze(data));
|
||||
serializationTest(pv);
|
||||
}
|
||||
|
||||
void testNonInitialized(std::ostream& ofile) {
|
||||
ofile<<"Testing non-initialized...\n";
|
||||
static const boolean bdata[] = {0, 1, 0, 1, 1};
|
||||
|
||||
static const int8 i8data[] = { 0, 1, 2, -1, BYTE_MAX_VALUE, BYTE_MAX_VALUE-1,
|
||||
BYTE_MIN_VALUE+1, BYTE_MIN_VALUE };
|
||||
static const uint8 u8data[] = { 0, 1, 2, -1, UBYTE_MAX_VALUE, UBYTE_MAX_VALUE-1 };
|
||||
|
||||
static const int16 i16data[] = { 0, 1, 2, -1, SHORT_MAX_VALUE, SHORT_MAX_VALUE-1,
|
||||
SHORT_MIN_VALUE+1, SHORT_MIN_VALUE };
|
||||
static const uint16 u16data[] = { 0, 1, 2, -1, USHORT_MAX_VALUE, USHORT_MAX_VALUE-1 };
|
||||
|
||||
static const int32 i32data[] = { 0, 1, 2, -1, INT_MAX_VALUE, INT_MAX_VALUE-1,
|
||||
INT_MIN_VALUE+1, INT_MIN_VALUE };
|
||||
static const uint32 u32data[] = { 0, 1, 2, -1, UINT_MAX_VALUE, UINT_MAX_VALUE-1 };
|
||||
|
||||
static const int64 i64data[] = { 0, 1, 2, -1, LONG_MAX_VALUE, LONG_MAX_VALUE-1,
|
||||
LONG_MIN_VALUE+1, LONG_MIN_VALUE };
|
||||
static const uint64 u64data[] = { 0, 1, 2, -1, ULONG_MAX_VALUE, ULONG_MAX_VALUE-1 };
|
||||
|
||||
static const double ddata[] = { (double)0.0, (double)1.1, (double)2.3, (double)-1.4,
|
||||
DOUBLE_MAX_VALUE, DOUBLE_MAX_VALUE-(double)123456.789,
|
||||
DOUBLE_MIN_VALUE+(double)1.1, DOUBLE_MIN_VALUE };
|
||||
|
||||
static const float fdata[] = { (float)0.0, (float)1.1, (float)2.3, (float)-1.4,
|
||||
FLOAT_MAX_VALUE, FLOAT_MAX_VALUE-(float)123456.789,
|
||||
FLOAT_MIN_VALUE+(float)1.1, FLOAT_MIN_VALUE };
|
||||
|
||||
static const String sdata[] = {
|
||||
"",
|
||||
"a",
|
||||
"a b",
|
||||
" ",
|
||||
"test",
|
||||
"smile",
|
||||
"this is a little longer string... maybe a little but longer... this makes test better",
|
||||
String(10000, 'b')
|
||||
};
|
||||
|
||||
void testArray() {
|
||||
testDiag("Testing arrays...");
|
||||
|
||||
testArrayType<PVBooleanArray>(bdata, NELEMENTS(bdata));
|
||||
|
||||
testArrayType<PVByteArray>(i8data, NELEMENTS(i8data));
|
||||
testArrayType<PVUByteArray>(u8data, NELEMENTS(u8data));
|
||||
testArrayType<PVShortArray>(i16data, NELEMENTS(i16data));
|
||||
testArrayType<PVUShortArray>(u16data, NELEMENTS(u16data));
|
||||
testArrayType<PVIntArray>(i32data, NELEMENTS(i32data));
|
||||
testArrayType<PVUIntArray>(u32data, NELEMENTS(u32data));
|
||||
testArrayType<PVLongArray>(i64data, NELEMENTS(i64data));
|
||||
testArrayType<PVULongArray>(u64data, NELEMENTS(u64data));
|
||||
|
||||
testArrayType<PVDoubleArray>(ddata, NELEMENTS(ddata));
|
||||
testArrayType<PVFloatArray>(fdata, NELEMENTS(fdata));
|
||||
|
||||
testArrayType<PVStringArray>(sdata, NELEMENTS(sdata));
|
||||
}
|
||||
|
||||
void testNonInitialized() {
|
||||
testDiag("Testing non-initialized...");
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
assert(factory.get()!=NULL);
|
||||
testOk1(factory.get()!=NULL);
|
||||
|
||||
// be sure all is covered
|
||||
for (int i = pvBoolean; i < pvString; i++)
|
||||
@@ -558,17 +346,15 @@ void testNonInitialized(std::ostream& ofile) {
|
||||
// and a structure array
|
||||
PVStructureArrayPtr structureArray = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure->getStructure()));
|
||||
serializationTest(structureArray);
|
||||
|
||||
ofile<<"!!! PASSED\n\n";
|
||||
}
|
||||
|
||||
void testStructure(std::ostream& ofile) {
|
||||
ofile<<"Testing structure...\n";
|
||||
void testStructure() {
|
||||
testDiag("Testing structure...");
|
||||
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
assert(factory.get()!=NULL);
|
||||
testOk1(factory.get()!=NULL);
|
||||
|
||||
ofile<<"\tSimple structure serialization\n";
|
||||
testDiag("\tSimple structure serialization");
|
||||
PVStructurePtr pvStructure = factory->createPVStructure(getStandardField()->timeStamp());
|
||||
pvStructure->getLongField("secondsPastEpoch")->put(123);
|
||||
pvStructure->getIntField("nanoSeconds")->put(456);
|
||||
@@ -576,21 +362,47 @@ void testStructure(std::ostream& ofile) {
|
||||
|
||||
serializationTest(pvStructure);
|
||||
|
||||
ofile<<"\tComplex structure serialization\n";
|
||||
testDiag("\tComplex structure serialization");
|
||||
pvStructure = factory->createPVStructure(
|
||||
getStandardField()->structureArray(
|
||||
getStandardField()->timeStamp(), "alarm,control,display,timeStamp")
|
||||
);
|
||||
// TODO fill with data
|
||||
serializationTest(pvStructure);
|
||||
}
|
||||
|
||||
ofile<<"!!! PASSED\n\n";
|
||||
void testStructureArray() {
|
||||
testDiag("Testing structure array...");
|
||||
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
testOk1(factory.get()!=NULL);
|
||||
|
||||
StructureArrayConstPtr tstype(
|
||||
getFieldCreate()->createStructureArray(getStandardField()->alarm()));
|
||||
PVStructureArrayPtr pvArr = getPVDataCreate()->createPVStructureArray(tstype);
|
||||
|
||||
testDiag("empty array");
|
||||
serializationTest(pvArr);
|
||||
|
||||
pvArr->setLength(10);
|
||||
|
||||
testDiag("All NULLs");
|
||||
serializationTest(pvArr);
|
||||
|
||||
PVStructureArray::svector data(5);
|
||||
|
||||
data[1] = getPVDataCreate()->createPVStructure(getStandardField()->alarm());
|
||||
data[4] = getPVDataCreate()->createPVStructure(getStandardField()->alarm());
|
||||
|
||||
pvArr->replace(freeze(data));
|
||||
|
||||
testDiag("Some NULLs");
|
||||
serializationTest(pvArr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void testStructureId(std::ostream& ofile) {
|
||||
ofile<<"Testing structureID...\n";
|
||||
void testStructureId() {
|
||||
testDiag("Testing structureID...");
|
||||
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
|
||||
@@ -607,15 +419,13 @@ void testStructureId(std::ostream& ofile) {
|
||||
StructureConstPtr structure2 = fieldCreate->createStructure("id2", fieldNames, fields);
|
||||
|
||||
|
||||
assert(structureWithNoId!=structure1);
|
||||
assert(structure1!=structure2);
|
||||
testOk1(structureWithNoId!=structure1);
|
||||
testOk1(structure1!=structure2);
|
||||
|
||||
//serializationTest(structure1);
|
||||
|
||||
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(structure1);
|
||||
serializationTest(pvStructure);
|
||||
|
||||
ofile<<"!!! PASSED\n\n";
|
||||
}
|
||||
|
||||
void serializatioTest(FieldConstPtr const & field)
|
||||
@@ -631,17 +441,15 @@ void serializatioTest(FieldConstPtr const & field)
|
||||
FieldConstPtr deserializedField = getFieldCreate()->deserialize(buffer, control);
|
||||
|
||||
// must equal
|
||||
bool isEqual = *field == *deserializedField;
|
||||
assert(isEqual);
|
||||
//assertEquals("field " + field.toString() + " serialization broken", field, deserializedField);
|
||||
testOk1(*field == *deserializedField);
|
||||
}
|
||||
|
||||
void testIntrospectionSerialization(std::ostream& ofile)
|
||||
void testIntrospectionSerialization()
|
||||
{
|
||||
ofile<<"Testing introspection serialization...\n";
|
||||
testDiag("Testing introspection serialization...");
|
||||
|
||||
FieldCreatePtr factory = getFieldCreate();
|
||||
assert(factory.get()!=NULL);
|
||||
testOk1(factory.get()!=NULL);
|
||||
|
||||
// be sure all is covered
|
||||
for (int i = pvBoolean; i < pvString; i++)
|
||||
@@ -662,42 +470,35 @@ void testIntrospectionSerialization(std::ostream& ofile)
|
||||
// and a structure array
|
||||
StructureArrayConstPtr structureArray = factory->createStructureArray(structure);
|
||||
serializatioTest(structureArray);
|
||||
|
||||
ofile<<"!!! PASSED\n\n";
|
||||
}
|
||||
|
||||
void testStringCopy(std::ostream& ofile) {
|
||||
void testStringCopy() {
|
||||
String s1 = "abc";
|
||||
String s2 = s1;
|
||||
if (s1.c_str() != s2.c_str())
|
||||
ofile << "\n!!! implementation of epics::pvData::String assignment operator does not share content !!!\n\n";
|
||||
testDiag("implementation of epics::pvData::String assignment operator does not share content");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::ofstream outfile;
|
||||
std::ostream *out=NULL;
|
||||
if(argc>1) {
|
||||
outfile.open(argv[1]);
|
||||
if(outfile.is_open()){
|
||||
out=&outfile;
|
||||
}else{
|
||||
fprintf(stderr, "Failed to open test output file\n");
|
||||
}
|
||||
}
|
||||
if(!out) out=&std::cout;
|
||||
} // end namespace
|
||||
|
||||
MAIN(testSerialization) {
|
||||
|
||||
testPlan(175);
|
||||
|
||||
flusher = new SerializableControlImpl();
|
||||
control = new DeserializableControlImpl();
|
||||
buffer = new ByteBuffer(1<<16);
|
||||
|
||||
testStringCopy(*out);
|
||||
testStringCopy();
|
||||
|
||||
testIntrospectionSerialization(*out);
|
||||
testEquals(*out);
|
||||
testNonInitialized(*out);
|
||||
testIntrospectionSerialization();
|
||||
testEquals();
|
||||
testNonInitialized();
|
||||
|
||||
testScalar(*out);
|
||||
testArray(*out);
|
||||
testStructure(*out);
|
||||
testScalar();
|
||||
testArray();
|
||||
testStructure();
|
||||
testStructureArray();
|
||||
|
||||
|
||||
delete buffer;
|
||||
@@ -705,6 +506,6 @@ int main(int argc, char *argv[]) {
|
||||
delete flusher;
|
||||
|
||||
epicsExitCallAtExits();
|
||||
return 0;
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
558
testApp/misc/testSharedVector.cpp
Normal file
558
testApp/misc/testSharedVector.cpp
Normal file
@@ -0,0 +1,558 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Author: Michael Davidsaver */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include "pv/sharedVector.h"
|
||||
|
||||
static void testEmpty()
|
||||
{
|
||||
testDiag("Test empty vector");
|
||||
epics::pvData::shared_vector<int> empty, empty2;
|
||||
|
||||
testOk1(empty.size()==0);
|
||||
testOk1(empty.empty());
|
||||
testOk1(empty.begin()==empty.end());
|
||||
testOk1(empty.unique());
|
||||
|
||||
testOk1(empty.data()==NULL);
|
||||
|
||||
testOk1(empty==empty);
|
||||
testOk1(!(empty!=empty));
|
||||
testOk1(empty==empty2);
|
||||
testOk1(!(empty!=empty2));
|
||||
}
|
||||
|
||||
static void testInternalAlloc()
|
||||
{
|
||||
testDiag("Test vector alloc w/ new[]");
|
||||
|
||||
epics::pvData::shared_vector<int> internal(5);
|
||||
|
||||
testOk1(internal.size()==5);
|
||||
testOk1(!internal.empty());
|
||||
testOk1(internal.unique());
|
||||
testOk1(internal.data()!=NULL);
|
||||
|
||||
testOk1(internal.begin()+5==internal.end());
|
||||
testOk1(internal.begin()==internal.end()-5);
|
||||
testOk1(internal.begin()+2==internal.end()-3);
|
||||
testOk1(internal.end()-internal.begin()==5);
|
||||
|
||||
internal[2] = 42;
|
||||
testOk1(internal[2]==42);
|
||||
|
||||
epics::pvData::shared_vector<int> internal2(15, 500);
|
||||
|
||||
testOk1(internal2.size()==15);
|
||||
testOk1(internal2[1]==500);
|
||||
|
||||
internal.swap(internal2);
|
||||
|
||||
testOk1(internal2.size()==5);
|
||||
testOk1(internal.size()==15);
|
||||
|
||||
internal.clear();
|
||||
|
||||
testOk1(internal.size()==0);
|
||||
testOk1(internal.empty());
|
||||
testOk1(internal.unique());
|
||||
testOk1(internal.data()==NULL);
|
||||
}
|
||||
|
||||
namespace {
|
||||
//Note: STL shared_ptr requires that deletors be copy constructable
|
||||
template<typename E>
|
||||
struct callCounter {
|
||||
std::tr1::shared_ptr<int> count;
|
||||
callCounter():count(new int){*count=0;}
|
||||
callCounter(const callCounter& o):count(o.count) {};
|
||||
callCounter& operator=(const callCounter& o){count=o.count;}
|
||||
void operator()(E){*count=1;}
|
||||
};
|
||||
}
|
||||
|
||||
static void testExternalAlloc()
|
||||
{
|
||||
testDiag("Test vector external alloc");
|
||||
|
||||
// Simulate a failed malloc() or similar
|
||||
int *oops=0;
|
||||
epics::pvData::shared_vector<int> nullPtr(oops, 42, 100);
|
||||
|
||||
testOk1(nullPtr.size()==0);
|
||||
testOk1(nullPtr.empty());
|
||||
testOk1(nullPtr.begin()==nullPtr.end());
|
||||
testOk1(nullPtr.unique());
|
||||
|
||||
testOk1(nullPtr.data()==NULL);
|
||||
|
||||
int *raw=new int[5];
|
||||
epics::pvData::shared_vector<int> newData(raw, 1, 4);
|
||||
|
||||
testOk1(newData.size()==4);
|
||||
testOk1(!newData.empty());
|
||||
|
||||
// check that offset is used
|
||||
raw[1]=14;
|
||||
testOk1(newData[0]==14);
|
||||
|
||||
// Check use of custom deleter
|
||||
int localVar[4] = {1,2,3,4};
|
||||
callCounter<int*> tracker;
|
||||
testOk1(*tracker.count==0);
|
||||
|
||||
epics::pvData::shared_vector<int> locvar(localVar,
|
||||
tracker,
|
||||
0, 4);
|
||||
|
||||
testOk1(locvar[1]==2);
|
||||
testOk1(*tracker.count==0);
|
||||
|
||||
newData.swap(locvar);
|
||||
|
||||
testOk1(*tracker.count==0);
|
||||
|
||||
newData.clear();
|
||||
|
||||
testOk1(*tracker.count==1);
|
||||
}
|
||||
|
||||
static void testShare()
|
||||
{
|
||||
testDiag("Test vector Sharing");
|
||||
|
||||
epics::pvData::shared_vector<int> one, two(15);
|
||||
epics::pvData::shared_vector<int> three(two);
|
||||
|
||||
testOk1(one.unique());
|
||||
testOk1(!two.unique());
|
||||
testOk1(!three.unique());
|
||||
|
||||
testOk1(two.data() == three.data());
|
||||
|
||||
one = two;
|
||||
|
||||
testOk1(!one.unique());
|
||||
|
||||
testOk1(two.data() == one.data());
|
||||
|
||||
one = one; // no-op
|
||||
|
||||
testOk1(two.data() == one.data());
|
||||
|
||||
one[1] = 43;
|
||||
testOk1(two[1]==43);
|
||||
testOk1(three[1]==43);
|
||||
|
||||
one.make_unique();
|
||||
|
||||
testOk1(one[1]==43);
|
||||
one[1] = 143;
|
||||
testOk1(two[1]==43);
|
||||
testOk1(three[1]==43);
|
||||
|
||||
two.resize(two.size());
|
||||
|
||||
testOk1(two[1]==43);
|
||||
two[1] = 243;
|
||||
testOk1(one[1]==143);
|
||||
testOk1(three[1]==43);
|
||||
|
||||
testOk1(one.unique());
|
||||
testOk1(two.unique());
|
||||
testOk1(three.unique());
|
||||
|
||||
one.resize(2);
|
||||
|
||||
testOk1(one.size()==2);
|
||||
testOk1(one[1]==143);
|
||||
testOk1(two.size()==15);
|
||||
testOk1(three.size()==15);
|
||||
|
||||
two.resize(20, 5000);
|
||||
|
||||
testOk1(two[1]==243);
|
||||
testOk1(one.size()==2);
|
||||
testOk1(two.size()==20);
|
||||
testOk1(three.size()==15);
|
||||
|
||||
testOk1(two[19]==5000);
|
||||
}
|
||||
|
||||
static void testConst()
|
||||
{
|
||||
testDiag("Test constant vector");
|
||||
|
||||
epics::pvData::shared_vector<int> writable(15, 100);
|
||||
|
||||
epics::pvData::shared_vector<int>::reference wr = writable[0];
|
||||
epics::pvData::shared_vector<int>::const_reference ror = writable[0];
|
||||
|
||||
testOk1(wr==ror);
|
||||
|
||||
int *compare = writable.data();
|
||||
|
||||
testOk1(writable.unique());
|
||||
|
||||
// can re-target container, but data is R/O
|
||||
epics::pvData::shared_vector<const int> rodata(freeze(writable));
|
||||
|
||||
epics::pvData::shared_vector<const int>::reference wcr = rodata[0];
|
||||
epics::pvData::shared_vector<const int>::const_reference rocr = rodata[0];
|
||||
|
||||
testOk1(wcr==rocr);
|
||||
|
||||
testOk1(rodata.data()==compare);
|
||||
writable = thaw(rodata);
|
||||
|
||||
testOk1(writable.data()==compare);
|
||||
|
||||
rodata = freeze(writable);
|
||||
|
||||
testOk1(rodata.data()==compare);
|
||||
|
||||
epics::pvData::shared_vector<const int> rodata2(rodata);
|
||||
|
||||
testOk1(rodata.data()==rodata2.data());
|
||||
|
||||
rodata2.make_unique();
|
||||
|
||||
testOk1(rodata.data()!=rodata2.data());
|
||||
}
|
||||
|
||||
static void testSlice()
|
||||
{
|
||||
testDiag("Test vector slicing");
|
||||
|
||||
epics::pvData::shared_vector<int> original(10, 100);
|
||||
|
||||
epics::pvData::shared_vector<int> half1(original), half2(original), half2a(original);
|
||||
|
||||
half1.slice(0, 5);
|
||||
half2.slice(5, 5);
|
||||
half2a.slice(5);
|
||||
|
||||
testOk1(half1.dataOffset()==0);
|
||||
testOk1(half2.dataOffset()==5);
|
||||
testOk1(half2a.dataOffset()==5);
|
||||
|
||||
testOk1(half1.size()==5);
|
||||
testOk1(half2.size()==5);
|
||||
testOk1(half2a.size()==5);
|
||||
|
||||
testOk1(half1.dataTotal()==10);
|
||||
testOk1(half2.dataTotal()==5);
|
||||
testOk1(half2a.dataTotal()==5);
|
||||
|
||||
testOk1(original.data() == half1.data());
|
||||
testOk1(half2.data() == half2a.data());
|
||||
|
||||
half1.slice(100000);
|
||||
half2.slice(1);
|
||||
half2a.slice(1,1);
|
||||
|
||||
testOk1(half1.dataOffset()==5);
|
||||
testOk1(half2.dataOffset()==6);
|
||||
testOk1(half2a.dataOffset()==6);
|
||||
|
||||
testOk1(half1.size()==0);
|
||||
testOk1(half2.size()==4);
|
||||
testOk1(half2a.size()==1);
|
||||
|
||||
testOk1(half1.dataTotal()==5);
|
||||
testOk1(half2.dataTotal()==4);
|
||||
testOk1(half2a.dataTotal()==4);
|
||||
|
||||
half2.clear();
|
||||
testOk1(half2.dataOffset()==0);
|
||||
testOk1(half2.dataCount()==0);
|
||||
testOk1(half2.dataTotal()==0);
|
||||
testOk1(half2.data()==NULL);
|
||||
}
|
||||
|
||||
static void testCapacity()
|
||||
{
|
||||
testDiag("Test vector capacity");
|
||||
|
||||
epics::pvData::shared_vector<int> vect(10, 100);
|
||||
|
||||
int *peek = vect.dataPtr().get();
|
||||
|
||||
vect.slice(0, 5);
|
||||
|
||||
testOk1(vect.size()==5);
|
||||
testOk1(vect.dataTotal()==10);
|
||||
testOk1(vect.dataPtr().get() == peek);
|
||||
|
||||
vect.resize(6);
|
||||
|
||||
testOk1(vect.dataPtr().get() == peek);
|
||||
testOk1(vect.size()==6);
|
||||
testOk1(vect.dataTotal()==10);
|
||||
|
||||
vect.resize(10);
|
||||
|
||||
testOk1(vect.dataPtr().get() == peek);
|
||||
testOk1(vect.size()==10);
|
||||
testOk1(vect.dataTotal()==10);
|
||||
|
||||
vect.resize(11);
|
||||
|
||||
testOk1(vect.dataPtr().get() != peek);
|
||||
testOk1(vect.size()==11);
|
||||
testOk1(vect.dataTotal()>=11);
|
||||
|
||||
vect[1] = 124;
|
||||
|
||||
vect.reserve(15);
|
||||
|
||||
testOk1(vect.size()==11);
|
||||
testOk1(vect.dataTotal()>=15);
|
||||
|
||||
testOk1(vect[1]==124);
|
||||
}
|
||||
|
||||
static void testPush()
|
||||
{
|
||||
epics::pvData::shared_vector<int> vect;
|
||||
|
||||
testDiag("Test push_back optimizations");
|
||||
|
||||
size_t nallocs = 0;
|
||||
size_t cap = vect.capacity();
|
||||
|
||||
for(size_t s=0; s<16*1024; s++) {
|
||||
vect.push_back(s);
|
||||
|
||||
if(cap!=vect.capacity()) {
|
||||
nallocs++;
|
||||
cap = vect.capacity();
|
||||
}
|
||||
}
|
||||
|
||||
testDiag("push_back %ld times caused %ld re-allocations",
|
||||
(unsigned long)vect.size(),
|
||||
(unsigned long)nallocs);
|
||||
|
||||
testOk1(nallocs==26);
|
||||
}
|
||||
|
||||
static void testVoid()
|
||||
{
|
||||
testDiag("Test vecter cast to/from void");
|
||||
|
||||
epics::pvData::shared_vector<int> typed(4);
|
||||
|
||||
epics::pvData::shared_vector<void> untyped2(epics::pvData::static_shared_vector_cast<void>(typed));
|
||||
|
||||
testOk1(typed.dataPtr().get()==untyped2.dataPtr().get());
|
||||
testOk1(typed.size()*sizeof(int)==untyped2.size());
|
||||
|
||||
untyped2.slice(sizeof(int), 2*sizeof(int));
|
||||
|
||||
typed = epics::pvData::static_shared_vector_cast<int>(untyped2);
|
||||
|
||||
testOk1(typed.dataOffset()==1);
|
||||
testOk1(typed.size()==2);
|
||||
}
|
||||
|
||||
struct dummyStruct {};
|
||||
|
||||
static void testNonPOD()
|
||||
{
|
||||
testDiag("Test vector of non-POD types");
|
||||
|
||||
epics::pvData::shared_vector<std::string> strings(6);
|
||||
epics::pvData::shared_vector<std::tr1::shared_ptr<dummyStruct> > structs(5);
|
||||
|
||||
testOk1(strings[0].empty());
|
||||
testOk1(structs[0].get()==NULL);
|
||||
|
||||
structs[1].reset(new dummyStruct);
|
||||
dummyStruct *temp = structs[1].get();
|
||||
|
||||
epics::pvData::shared_vector<std::tr1::shared_ptr<dummyStruct> > structs2(structs);
|
||||
|
||||
testOk1(!structs.unique());
|
||||
testOk1(structs[1].unique());
|
||||
|
||||
testOk1(structs2[1].get()==temp);
|
||||
|
||||
structs2.make_unique();
|
||||
|
||||
testOk1(structs.unique());
|
||||
testOk1(!structs[1].unique());
|
||||
|
||||
testOk1(structs2[1].get()==temp);
|
||||
}
|
||||
|
||||
static void testVectorConvert()
|
||||
{
|
||||
testDiag("Test shared_vector_convert");
|
||||
|
||||
epics::pvData::shared_vector<int> ints(6, 42), moreints;
|
||||
epics::pvData::shared_vector<float> floats;
|
||||
epics::pvData::shared_vector<std::string> strings;
|
||||
epics::pvData::shared_vector<void> voids;
|
||||
|
||||
testOk1(ints.unique());
|
||||
|
||||
// no-op convert. Just returns another reference
|
||||
moreints = epics::pvData::shared_vector_convert<int>(ints);
|
||||
|
||||
testOk1(!ints.unique());
|
||||
moreints.clear();
|
||||
|
||||
// conversion when both types are known.
|
||||
// returns a new vector
|
||||
floats = epics::pvData::shared_vector_convert<float>(ints);
|
||||
|
||||
testOk1(ints.unique());
|
||||
testOk1(floats.size()==ints.size());
|
||||
testOk1(floats.at(0)==42.0);
|
||||
|
||||
// convert to void is static_shared_vector_cast<void>()
|
||||
// returns a reference
|
||||
voids = epics::pvData::shared_vector_convert<void>(ints);
|
||||
|
||||
testOk1(!ints.unique());
|
||||
testOk1(voids.size()==ints.size()*sizeof(int));
|
||||
|
||||
// convert from void uses shared_vector<void>::original_type()
|
||||
// to find that the actual type is 'int'.
|
||||
// returns a new vector
|
||||
strings = epics::pvData::shared_vector_convert<std::string>(voids);
|
||||
|
||||
voids.clear();
|
||||
|
||||
testOk1(ints.unique());
|
||||
testOk1(strings.size()==ints.size());
|
||||
testOk1(strings.at(0)=="42");
|
||||
}
|
||||
|
||||
static void testWeak()
|
||||
{
|
||||
testDiag("Test weak_ptr counting");
|
||||
|
||||
epics::pvData::shared_vector<int> data(6);
|
||||
|
||||
testOk1(data.unique());
|
||||
|
||||
std::tr1::shared_ptr<int> pdata(data.dataPtr());
|
||||
|
||||
testOk1(!data.unique());
|
||||
|
||||
pdata.reset();
|
||||
|
||||
testOk1(data.unique());
|
||||
|
||||
std::tr1::weak_ptr<int> wdata(data.dataPtr());
|
||||
|
||||
testOk1(data.unique()); // True, but I wish it wasn't!!!
|
||||
|
||||
pdata = wdata.lock();
|
||||
|
||||
testOk1(!data.unique());
|
||||
}
|
||||
|
||||
static void testICE()
|
||||
{
|
||||
testDiag("Test freeze and thaw");
|
||||
|
||||
epics::pvData::shared_vector<int> A(6, 42), C;
|
||||
epics::pvData::shared_vector<const int> B, D;
|
||||
|
||||
int *check = A.data();
|
||||
|
||||
// check freeze w/ unique reference
|
||||
|
||||
// clears A and moves reference to B
|
||||
// no copy
|
||||
B = epics::pvData::freeze(A);
|
||||
|
||||
testOk1(A.unique());
|
||||
testOk1(B.unique());
|
||||
testOk1(A.size()==0);
|
||||
testOk1(B.size()==6);
|
||||
testOk1(A.data()!=check);
|
||||
testOk1(B.data()==check);
|
||||
|
||||
D = B; // create second const reference
|
||||
|
||||
// clears D, but reference to B refrence
|
||||
// to B remains, so a copy is made
|
||||
C = epics::pvData::thaw(D);
|
||||
|
||||
testOk1(B.unique());
|
||||
testOk1(C.unique());
|
||||
testOk1(B.size()==6);
|
||||
testOk1(C.size()==6);
|
||||
testOk1(B.data()==check);
|
||||
testOk1(C.data()!=NULL);
|
||||
testOk1(C.at(0)==42);
|
||||
|
||||
C.clear();
|
||||
|
||||
// clears B and moves reference to A
|
||||
// no copy
|
||||
A = epics::pvData::thaw(B);
|
||||
|
||||
testOk1(A.unique());
|
||||
testOk1(B.unique());
|
||||
testOk1(A.size()==6);
|
||||
testOk1(B.size()==0);
|
||||
testOk1(A.data()==check);
|
||||
testOk1(B.data()!=check);
|
||||
|
||||
C = A; // create second non-const reference
|
||||
|
||||
testOk1(!A.unique());
|
||||
|
||||
try {
|
||||
// would clear A, but remaining reference C
|
||||
// fails operation. A not cleared
|
||||
// and exception thrown
|
||||
B = epics::pvData::freeze(A);
|
||||
testFail("Froze non-unique vector!");
|
||||
} catch(std::runtime_error& e) {
|
||||
testPass("freeze of non-unique throws runtime_error as expected");
|
||||
}
|
||||
}
|
||||
|
||||
MAIN(testSharedVector)
|
||||
{
|
||||
testPlan(162);
|
||||
testDiag("Tests for shared_vector");
|
||||
|
||||
testDiag("sizeof(shared_vector<int>)=%lu",
|
||||
(unsigned long)sizeof(epics::pvData::shared_vector<int>));
|
||||
|
||||
testEmpty();
|
||||
testInternalAlloc();
|
||||
testExternalAlloc();
|
||||
testCapacity();
|
||||
testShare();
|
||||
testConst();
|
||||
testSlice();
|
||||
testPush();
|
||||
testVoid();
|
||||
testNonPOD();
|
||||
testVectorConvert();
|
||||
testWeak();
|
||||
testICE();
|
||||
return testDone();
|
||||
}
|
||||
407
testApp/misc/testTypeCast.cpp
Normal file
407
testApp/misc/testTypeCast.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Author: Michael Davidsaver */
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <float.h>
|
||||
#include <epicsMath.h>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include "pv/typeCast.h"
|
||||
|
||||
using epics::pvData::String;
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T>
|
||||
struct testequal {
|
||||
static bool op(T A, T B) {return A==B; }
|
||||
};
|
||||
template<>
|
||||
struct testequal<double> {
|
||||
static bool op(double A, double B) {return fabs(A-B)<1e-300; }
|
||||
};
|
||||
template<>
|
||||
struct testequal<float> {
|
||||
static bool op(float A, float B) {return fabs(A-B)<1e-30; }
|
||||
};
|
||||
|
||||
template<typename TO, typename FROM>
|
||||
struct testcase {
|
||||
static void op(TO expect, FROM inp)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
TO actual;
|
||||
try {
|
||||
actual = ::epics::pvData::castUnsafe<TO,FROM>(inp);
|
||||
//actual = ::epics::pvData::detail::cast_helper<TO,FROM>::op(inp);
|
||||
} catch(std::runtime_error& e) {
|
||||
msg<<"Failed to cast "
|
||||
<<inp<<" ("<<typeid(FROM).name()<<") -> "
|
||||
<<expect<<" ("<<typeid(TO).name()<<")\n Error: "
|
||||
<<typeid(e).name()<<"("<<e.what()<<")";
|
||||
testFail("%s", msg.str().c_str());
|
||||
return;
|
||||
}
|
||||
if(!testequal<TO>::op(actual, expect)) {
|
||||
msg<<"Failed cast gives unexpected value "
|
||||
<<inp<<" ("<<typeid(FROM).name()<<") -> "
|
||||
<<expect<<" ("<<typeid(TO).name()<<") yields: "
|
||||
<<actual;
|
||||
testFail("%s", msg.str().c_str());
|
||||
return;
|
||||
}
|
||||
msg<<"cast "
|
||||
<<inp<<" ("<<typeid(FROM).name()<<") -> "
|
||||
<<expect<<" ("<<typeid(TO).name()<<") yields: "
|
||||
<<actual;
|
||||
testPass("%s", msg.str().c_str());
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename TO, typename FROM>
|
||||
struct testfail {
|
||||
static void op(FROM inp)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
TO actual;
|
||||
try {
|
||||
actual = ::epics::pvData::castUnsafe<TO,FROM>(inp);
|
||||
msg<<"Failed to generate expected error "
|
||||
<<inp<<" ("<<typeid(FROM).name()<<") -> ("
|
||||
<<typeid(TO).name()<<") yields: "
|
||||
<<actual;
|
||||
testFail("%s", msg.str().c_str());
|
||||
return;
|
||||
} catch(std::runtime_error& e) {
|
||||
msg<<"Got expected error "
|
||||
<<inp<<" ("<<typeid(FROM).name()<<") -> ("
|
||||
<<typeid(TO).name()<<") fails with: "
|
||||
<<e.what();
|
||||
testPass("%s", msg.str().c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Test cast
|
||||
#define TEST(TTO, VTO, TFRO, VFRO) testcase<TTO, TFRO>::op(VTO, VFRO)
|
||||
|
||||
// Test cast and reverse
|
||||
#define TEST2(TTO, VTO, TFRO, VFRO) TEST(TTO, VTO, TFRO, VFRO); TEST(TFRO, VFRO, TTO, VTO)
|
||||
|
||||
#define FAIL(TTO, TFRO, VFRO) testfail<TTO,TFRO>::op(VFRO)
|
||||
|
||||
} // end namespace
|
||||
|
||||
|
||||
MAIN(testTypeCast)
|
||||
{
|
||||
testPlan(110);
|
||||
|
||||
try {
|
||||
|
||||
int8_t xint8=0;
|
||||
uint8_t xuint8=0;
|
||||
int16_t xint16=0;
|
||||
uint16_t xuint16=0;
|
||||
int32_t xint32=0;
|
||||
uint32_t xuint32=0;
|
||||
int64_t xint64=0;
|
||||
uint64_t xuint64=0;
|
||||
float xfloat=0.0;
|
||||
double xdouble=0.0;
|
||||
epics::pvData::String xString("0");
|
||||
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
typedef epics::pvData::String String_t;
|
||||
|
||||
// force all possibilities to be compiled
|
||||
#define CHECK(M, N) x## M = ::epics::pvData::castUnsafe<M ##_t>(x## N); \
|
||||
std::transform(&x ## N, &x ## N+1, &x ## M, ::epics::pvData::castUnsafe<M ##_t,N ##_t>)
|
||||
//#define CHECK(M, N) x## M = ::epics::pvData::detail::cast_helper<M ##_t,N ##_t>::op(x## N)
|
||||
CHECK(int8, int8);
|
||||
CHECK(int8, uint8);
|
||||
CHECK(int8, int16);
|
||||
CHECK(int8, uint16);
|
||||
CHECK(int8, int32);
|
||||
CHECK(int8, uint32);
|
||||
CHECK(int8, int64);
|
||||
CHECK(int8, uint64);
|
||||
CHECK(int8, float);
|
||||
CHECK(int8, double);
|
||||
CHECK(int8, String);
|
||||
|
||||
CHECK(uint8, int8);
|
||||
CHECK(uint8, uint8);
|
||||
CHECK(uint8, int16);
|
||||
CHECK(uint8, uint16);
|
||||
CHECK(uint8, int32);
|
||||
CHECK(uint8, uint32);
|
||||
CHECK(uint8, int64);
|
||||
CHECK(uint8, uint64);
|
||||
CHECK(uint8, float);
|
||||
CHECK(uint8, double);
|
||||
CHECK(uint8, String);
|
||||
|
||||
CHECK(int16, int8);
|
||||
CHECK(int16, uint8);
|
||||
CHECK(int16, int16);
|
||||
CHECK(int16, uint16);
|
||||
CHECK(int16, int32);
|
||||
CHECK(int16, uint32);
|
||||
CHECK(int16, int64);
|
||||
CHECK(int16, uint64);
|
||||
CHECK(int16, float);
|
||||
CHECK(int16, double);
|
||||
CHECK(int16, String);
|
||||
|
||||
CHECK(uint16, int8);
|
||||
CHECK(uint16, uint8);
|
||||
CHECK(uint16, int16);
|
||||
CHECK(uint16, uint16);
|
||||
CHECK(uint16, int32);
|
||||
CHECK(uint16, uint32);
|
||||
CHECK(uint16, int64);
|
||||
CHECK(uint16, uint64);
|
||||
CHECK(uint16, float);
|
||||
CHECK(uint16, double);
|
||||
CHECK(uint16, String);
|
||||
|
||||
CHECK(int32, int8);
|
||||
CHECK(int32, uint8);
|
||||
CHECK(int32, int16);
|
||||
CHECK(int32, uint16);
|
||||
CHECK(int32, int32);
|
||||
CHECK(int32, uint32);
|
||||
CHECK(int32, int64);
|
||||
CHECK(int32, uint64);
|
||||
CHECK(int32, float);
|
||||
CHECK(int32, double);
|
||||
CHECK(int32, String);
|
||||
|
||||
CHECK(uint32, int8);
|
||||
CHECK(uint32, uint8);
|
||||
CHECK(uint32, int16);
|
||||
CHECK(uint32, uint16);
|
||||
CHECK(uint32, int32);
|
||||
CHECK(uint32, uint32);
|
||||
CHECK(uint32, int64);
|
||||
CHECK(uint32, uint64);
|
||||
CHECK(uint32, float);
|
||||
CHECK(uint32, double);
|
||||
CHECK(uint32, String);
|
||||
|
||||
CHECK(int64, int8);
|
||||
CHECK(int64, uint8);
|
||||
CHECK(int64, int16);
|
||||
CHECK(int64, uint16);
|
||||
CHECK(int64, int32);
|
||||
CHECK(int64, uint32);
|
||||
CHECK(int64, int64);
|
||||
CHECK(int64, uint64);
|
||||
CHECK(int64, float);
|
||||
CHECK(int64, double);
|
||||
//CHECK(int64, String);
|
||||
|
||||
CHECK(uint64, int8);
|
||||
CHECK(uint64, uint8);
|
||||
CHECK(uint64, int16);
|
||||
CHECK(uint64, uint16);
|
||||
CHECK(uint64, int32);
|
||||
CHECK(uint64, uint32);
|
||||
CHECK(uint64, int64);
|
||||
CHECK(uint64, uint64);
|
||||
CHECK(uint64, float);
|
||||
CHECK(uint64, double);
|
||||
//CHECK(uint64, String);
|
||||
|
||||
CHECK(float, int8);
|
||||
CHECK(float, uint8);
|
||||
CHECK(float, int16);
|
||||
CHECK(float, uint16);
|
||||
CHECK(float, int32);
|
||||
CHECK(float, uint32);
|
||||
CHECK(float, int64);
|
||||
CHECK(float, uint64);
|
||||
CHECK(float, float);
|
||||
CHECK(float, double);
|
||||
CHECK(float, String);
|
||||
|
||||
CHECK(double, int8);
|
||||
CHECK(double, uint8);
|
||||
CHECK(double, int16);
|
||||
CHECK(double, uint16);
|
||||
CHECK(double, int32);
|
||||
CHECK(double, uint32);
|
||||
CHECK(double, int64);
|
||||
CHECK(double, uint64);
|
||||
CHECK(double, float);
|
||||
CHECK(double, double);
|
||||
CHECK(double, String);
|
||||
|
||||
CHECK(String, int8);
|
||||
CHECK(String, uint8);
|
||||
CHECK(String, int16);
|
||||
CHECK(String, uint16);
|
||||
CHECK(String, int32);
|
||||
CHECK(String, uint32);
|
||||
CHECK(String, int64);
|
||||
CHECK(String, uint64);
|
||||
CHECK(String, float);
|
||||
CHECK(String, double);
|
||||
CHECK(String, String);
|
||||
#undef CHECK
|
||||
|
||||
testDiag("Integer signed <=> unsigned");
|
||||
|
||||
TEST2(uint8_t, std::numeric_limits<uint8_t>::max(), int8_t, -1);
|
||||
TEST2(uint16_t, std::numeric_limits<uint16_t>::max(), int8_t, -1);
|
||||
TEST2(uint32_t, std::numeric_limits<uint32_t>::max(), int8_t, -1);
|
||||
TEST2(uint64_t, std::numeric_limits<uint64_t>::max(), int8_t, -1);
|
||||
|
||||
testDiag("Integer unsigned promote (and demote when in range)");
|
||||
|
||||
TEST2(uint16_t, 0xff, uint8_t, 0xff);
|
||||
TEST2(uint32_t, 0xffff, uint16_t, 0xffff);
|
||||
TEST2(uint64_t, 0xffffffffu, uint32_t, 0xffffffffu);
|
||||
|
||||
TEST2(int16_t, 0x7f, int8_t, 0x7f);
|
||||
TEST2(int32_t, 0x7fff, int16_t, 0x7fff);
|
||||
TEST2(int64_t, 0x7fffffff, int32_t, 0x7fffffff);
|
||||
|
||||
testDiag("Double to int w/ round towards zero (aka truncation)");
|
||||
|
||||
TEST(int32_t, 2, double, 2.1);
|
||||
TEST(int32_t, 2, double, 2.5);
|
||||
TEST(int32_t, 2, double, 2.7);
|
||||
TEST(int32_t, -2, double, -2.1);
|
||||
TEST(int32_t, -2, double, -2.5);
|
||||
TEST(int32_t, -2, double, -2.7);
|
||||
|
||||
testDiag("Float to int w/ round towards zero (aka truncation)");
|
||||
|
||||
TEST(int32_t, 2, float, 2.1);
|
||||
TEST(int32_t, 2, float, 2.5);
|
||||
TEST(int32_t, 2, float, 2.7);
|
||||
TEST(int32_t, -2, float, -2.1);
|
||||
TEST(int32_t, -2, float, -2.5);
|
||||
TEST(int32_t, -2, float, -2.7);
|
||||
|
||||
testDiag("String Printing/parsing");
|
||||
|
||||
TEST2(String, "1", int32_t, 1);
|
||||
TEST2(String, "-1", int32_t, -1);
|
||||
TEST2(String, "1", int8_t, 1);
|
||||
TEST2(String, "-1", int8_t, -1);
|
||||
TEST2(String, "1", uint8_t, 1);
|
||||
TEST2(String, "-1", char, -1);
|
||||
|
||||
TEST2(String, "127", int32_t, std::numeric_limits<int8_t>::max());
|
||||
TEST2(String, "-128", int32_t, std::numeric_limits<int8_t>::min());
|
||||
TEST2(String, "255", int32_t, std::numeric_limits<uint8_t>::max());
|
||||
|
||||
TEST2(String, "32767", int32_t, std::numeric_limits<int16_t>::max());
|
||||
TEST2(String, "-32768", int32_t, std::numeric_limits<int16_t>::min());
|
||||
TEST2(String, "65535", int32_t, std::numeric_limits<uint16_t>::max());
|
||||
|
||||
TEST2(String, "2147483647", int32_t, std::numeric_limits<int32_t>::max());
|
||||
TEST2(String, "-2147483648", int32_t, std::numeric_limits<int32_t>::min());
|
||||
TEST2(String, "4294967295", uint32_t, std::numeric_limits<uint32_t>::max());
|
||||
|
||||
TEST2(String, "9223372036854775807", int64_t, std::numeric_limits<int64_t>::max());
|
||||
TEST2(String, "-9223372036854775808", int64_t, std::numeric_limits<int64_t>::min());
|
||||
TEST2(String, "18446744073709551615", uint64_t, std::numeric_limits<uint64_t>::max());
|
||||
|
||||
TEST2(String, "1.1", double, 1.1);
|
||||
TEST2(String, "1.1e+100", double, 1.1e100);
|
||||
TEST2(String, "1.1e-100", double, 1.1e-100);
|
||||
|
||||
TEST(double, 1.1e100, String, "1.1E+100");
|
||||
|
||||
testDiag("String Parsing");
|
||||
|
||||
TEST(int32_t, 15, String, "0xf");
|
||||
TEST(int32_t, 15, String, "0xF");
|
||||
TEST(int32_t, -15, String, "-0xF");
|
||||
TEST(int32_t, 16, String, "0x10");
|
||||
TEST(int32_t, -16, String, "-0x10");
|
||||
|
||||
TEST(int32_t, 7, String, "07");
|
||||
TEST(int32_t, 8, String, "010");
|
||||
TEST(int32_t, -7, String, "-07");
|
||||
TEST(int32_t, -8, String, "-010");
|
||||
|
||||
TEST(int64_t, 15, String, "0xf");
|
||||
TEST(int64_t, 15, String, "0xF");
|
||||
TEST(int64_t, -15, String, "-0xF");
|
||||
TEST(int64_t, 16, String, "0x10");
|
||||
TEST(int64_t, -16, String, "-0x10");
|
||||
|
||||
TEST(int64_t, 7, String, "07");
|
||||
TEST(int64_t, 8, String, "010");
|
||||
TEST(int64_t, -7, String, "-07");
|
||||
TEST(int64_t, -8, String, "-010");
|
||||
|
||||
testDiag("String parsing errors");
|
||||
|
||||
FAIL(int32_t, String, "hello!");
|
||||
FAIL(int32_t, String, "42 is the answer");
|
||||
FAIL(int64_t, String, "hello!");
|
||||
FAIL(int64_t, String, "42 is the answer");
|
||||
FAIL(double, String, "hello!");
|
||||
FAIL(double, String, "42 is the answer");
|
||||
|
||||
FAIL(int8_t, String, "1000");
|
||||
FAIL(int8_t, String, "-1000");
|
||||
;
|
||||
FAIL(double, String, "1e+10000000");
|
||||
|
||||
testDiag("Floating point overflows");
|
||||
|
||||
TEST(float, FLT_MAX, double, 1e300);
|
||||
TEST(float, -FLT_MAX, double, -1e300);
|
||||
TEST(float, FLT_MIN, double, 1e-300);
|
||||
TEST(float, -FLT_MIN, double, -1e-300);
|
||||
|
||||
xfloat = ::epics::pvData::castUnsafe<float,double>(epicsNAN);
|
||||
testOk(isnan( xfloat ), "Test cast double NAN to float NAN yields: %f", xfloat);
|
||||
|
||||
{
|
||||
std::string result[3];
|
||||
const int32_t in[3] = { 1234, 506001, 42424242 };
|
||||
|
||||
testDiag("Test vcast int32 -> String");
|
||||
epics::pvData::castUnsafeV(3, epics::pvData::pvString, (void*)result,
|
||||
epics::pvData::pvInt, (void*)in);
|
||||
testDiag("Yields %s %s %s", result[0].c_str(), result[1].c_str(), result[2].c_str());
|
||||
|
||||
testOk1(result[0]=="1234");
|
||||
testOk1(result[1]=="506001");
|
||||
testOk1(result[2]=="42424242");
|
||||
}
|
||||
|
||||
} catch(std::exception& e) {
|
||||
testAbort("Uncaught exception: %s", e.what());
|
||||
}
|
||||
|
||||
return testDone();
|
||||
}
|
||||
@@ -229,11 +229,11 @@ static void testEnumerated(FILE * fd,FILE */*auxfd*/)
|
||||
assert(result);
|
||||
int32 index = pvEnumerated.getIndex();
|
||||
String choice = pvEnumerated.getChoice();
|
||||
StringArrayPtr const & choices = pvEnumerated.getChoices();
|
||||
PVStringArray::const_svector choices = pvEnumerated.getChoices();
|
||||
int32 numChoices = pvEnumerated.getNumberChoices();
|
||||
if(debug) {
|
||||
fprintf(fd,"index %d choice %s choices",index,choice.c_str());
|
||||
for(int i=0; i<numChoices; i++ ) fprintf(fd," %s",(*choices)[i].c_str());
|
||||
for(int i=0; i<numChoices; i++ ) fprintf(fd," %s",choices[i].c_str());
|
||||
fprintf(fd,"\n");
|
||||
}
|
||||
pvEnumerated.setIndex(2);
|
||||
|
||||
@@ -9,6 +9,7 @@ testBitSetUtil_LIBS += pvData Com
|
||||
PROD_HOST += testIntrospect
|
||||
testIntrospect_SRCS += testIntrospect.cpp
|
||||
testIntrospect_LIBS += pvData Com
|
||||
TESTS += testIntrospect
|
||||
|
||||
PROD_HOST += testPVAppend
|
||||
testPVAppend_SRCS += testPVAppend.cpp
|
||||
@@ -38,18 +39,22 @@ PROD_HOST += testConvert
|
||||
testConvert_SRCS += testConvert.cpp
|
||||
testConvert_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testPVScalarArray
|
||||
TESTPROD += testPVScalarArray
|
||||
testPVScalarArray_SRCS += testPVScalarArray.cpp
|
||||
testPVScalarArray_LIBS += pvData Com
|
||||
TESTS += testPVScalarArray
|
||||
|
||||
PROD_HOST += testPVStructureArray
|
||||
testPVStructureArray_SRCS += testPVStructureArray.cpp
|
||||
testPVStructureArray_LIBS += pvData Com
|
||||
TESTS += testPVStructureArray
|
||||
|
||||
PROD_HOST += testOperators
|
||||
testOperators_SRCS += testOperators.cpp
|
||||
testOperators_LIBS += pvData Com
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include <epicsExit.h>
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/requester.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
@@ -23,750 +25,42 @@
|
||||
#include <pv/standardPVField.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
static bool debug = false;
|
||||
|
||||
static FieldCreatePtr fieldCreate;
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
static StandardFieldPtr standardField;
|
||||
static StandardPVFieldPtr standardPVField;
|
||||
static ConvertPtr convert;
|
||||
static String builder("");
|
||||
|
||||
static void testConvertScalar(FILE *fd) {
|
||||
PVScalarPtr pvBytePtr = pvDataCreate->createPVScalar(pvByte);
|
||||
PVScalarPtr pvUBytePtr = pvDataCreate->createPVScalar(pvUByte);
|
||||
PVScalarPtr pvShortPtr = pvDataCreate->createPVScalar(pvShort);
|
||||
PVScalarPtr pvUShortPtr = pvDataCreate->createPVScalar(pvUShort);
|
||||
PVScalarPtr pvIntPtr = pvDataCreate->createPVScalar(pvInt);
|
||||
PVScalarPtr pvUIntPtr = pvDataCreate->createPVScalar(pvUInt);
|
||||
PVScalarPtr pvLongPtr = pvDataCreate->createPVScalar(pvLong);
|
||||
PVScalarPtr pvULongPtr = pvDataCreate->createPVScalar(pvULong);
|
||||
PVScalarPtr pvFloatPtr = pvDataCreate->createPVScalar(pvFloat);
|
||||
PVScalarPtr pvDoublePtr = pvDataCreate->createPVScalar(pvDouble);
|
||||
|
||||
fprintf(fd,"testConvertScalar\n");
|
||||
if(debug) fprintf(fd,"\nfromByte\n");
|
||||
int8 bval = 127;
|
||||
for(int i=0; i<3; i++) {
|
||||
convert->fromByte(pvBytePtr, bval);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromByte(pvUBytePtr, bval);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromByte(pvShortPtr, bval);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromByte(pvUShortPtr, bval);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromByte(pvIntPtr, bval);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromByte(pvUIntPtr, bval);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromByte(pvLongPtr, bval);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromByte(pvULongPtr, bval);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromByte(pvFloatPtr, bval);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromByte(pvDoublePtr, bval);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUBytePtr, pvFloatPtr);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUBytePtr, pvDoublePtr);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
bval++;
|
||||
}
|
||||
fprintf(fd,"fromByte PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromShort\n");
|
||||
int16 sval = 0x7fff;
|
||||
for(int i=0; i<3; i++) {
|
||||
convert->fromShort(pvBytePtr, sval);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromShort(pvUBytePtr, sval);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromShort(pvShortPtr, sval);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromShort(pvUShortPtr, sval);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromShort(pvIntPtr, sval);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromShort(pvUIntPtr, sval);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromShort(pvLongPtr, sval);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromShort(pvULongPtr, sval);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromShort(pvFloatPtr, sval);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromShort(pvDoublePtr, sval);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUShortPtr, pvFloatPtr);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUShortPtr, pvDoublePtr);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
sval++;
|
||||
}
|
||||
fprintf(fd,"fromShort PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromInt\n");
|
||||
int32 ival = 0x7fffffff;
|
||||
for(int i=0; i<3; i++) {
|
||||
convert->fromInt(pvBytePtr, ival);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromInt(pvUBytePtr, ival);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromInt(pvShortPtr, ival);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromInt(pvUShortPtr, ival);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromInt(pvIntPtr, ival);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromInt(pvUIntPtr, ival);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromInt(pvLongPtr, ival);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromInt(pvULongPtr, ival);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromInt(pvFloatPtr, ival);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromInt(pvDoublePtr, ival);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUIntPtr, pvFloatPtr);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUIntPtr, pvDoublePtr);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
ival++;
|
||||
}
|
||||
fprintf(fd,"fromInt PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromLong\n");
|
||||
int64 lval = 0x7fffffffffffffffLL;
|
||||
for(int i=0; i<3; i++) {
|
||||
convert->fromLong(pvBytePtr, lval);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromLong(pvUBytePtr, lval);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromLong(pvShortPtr, lval);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromLong(pvUShortPtr, lval);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromLong(pvIntPtr, lval);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromLong(pvUIntPtr, lval);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromLong(pvLongPtr, lval);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromLong(pvULongPtr, lval);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromLong(pvFloatPtr, lval);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromLong(pvDoublePtr, lval);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalar(pvULongPtr, pvFloatPtr);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalar(pvULongPtr, pvDoublePtr);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
lval++;
|
||||
}
|
||||
fprintf(fd,"fromLong PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromUByte\n");
|
||||
uint8 ubval = 127;
|
||||
for(int i=0; i<3; i++) {
|
||||
convert->fromUByte(pvBytePtr, ubval);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromUByte(pvUBytePtr, ubval);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromUByte(pvShortPtr, ubval);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromUByte(pvUShortPtr, ubval);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromUByte(pvIntPtr, ubval);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromUByte(pvUIntPtr, ubval);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromUByte(pvLongPtr, ubval);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromUByte(pvULongPtr, ubval);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromUByte(pvFloatPtr, ubval);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromUByte(pvDoublePtr, ubval);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUBytePtr, pvFloatPtr);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUBytePtr, pvDoublePtr);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
ubval++;
|
||||
}
|
||||
fprintf(fd,"fromUByte PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromUShort\n");
|
||||
uint16 usval = 0x7fff;
|
||||
for(int i=0; i<3; i++) {
|
||||
convert->fromUShort(pvBytePtr, usval);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromUShort(pvUBytePtr, usval);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromUShort(pvShortPtr, usval);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromUShort(pvUShortPtr, usval);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromUShort(pvIntPtr, usval);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromUShort(pvUIntPtr, usval);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromUShort(pvLongPtr, usval);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromUShort(pvULongPtr, usval);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromUShort(pvFloatPtr, usval);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromUShort(pvDoublePtr, usval);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUShortPtr, pvFloatPtr);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUShortPtr, pvDoublePtr);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
usval++;
|
||||
}
|
||||
fprintf(fd,"fromUShort PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromUInt\n");
|
||||
uint32 uival = 0x7fffffff;
|
||||
for(int i=0; i<3; i++) {
|
||||
convert->fromUInt(pvBytePtr, uival);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromUInt(pvUBytePtr, uival);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromUInt(pvShortPtr, uival);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromUInt(pvUShortPtr, uival);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromUInt(pvIntPtr, uival);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromUInt(pvUIntPtr, uival);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromUInt(pvLongPtr, uival);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromUInt(pvULongPtr, uival);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromUInt(pvFloatPtr, uival);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromUInt(pvDoublePtr, uival);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUIntPtr, pvFloatPtr);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalar(pvUIntPtr, pvDoublePtr);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
uival++;
|
||||
}
|
||||
fprintf(fd,"fromUInt PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromULong\n");
|
||||
uint64 ulval = 0x7fffffffffffffffLL;
|
||||
for(int i=0; i<3; i++) {
|
||||
convert->fromULong(pvBytePtr, ulval);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromULong(pvUBytePtr, ulval);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromULong(pvShortPtr, ulval);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromULong(pvUShortPtr, ulval);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromULong(pvIntPtr, ulval);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromULong(pvUIntPtr, ulval);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromULong(pvLongPtr, ulval);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromULong(pvULongPtr, ulval);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromULong(pvFloatPtr, ulval);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromULong(pvDoublePtr, ulval);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalar(pvULongPtr, pvFloatPtr);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalar(pvULongPtr, pvDoublePtr);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
ulval++;
|
||||
}
|
||||
fprintf(fd,"fromULong PASSED\n");
|
||||
}
|
||||
|
||||
static void testConvertScalarArray(FILE *fd) {
|
||||
PVScalarArrayPtr pvBytePtr = pvDataCreate->createPVScalarArray(pvByte);
|
||||
PVScalarArrayPtr pvUBytePtr = pvDataCreate->createPVScalarArray(pvUByte);
|
||||
PVScalarArrayPtr pvShortPtr = pvDataCreate->createPVScalarArray(pvShort);
|
||||
PVScalarArrayPtr pvUShortPtr = pvDataCreate->createPVScalarArray(pvUShort);
|
||||
PVScalarArrayPtr pvIntPtr = pvDataCreate->createPVScalarArray(pvInt);
|
||||
PVScalarArrayPtr pvUIntPtr = pvDataCreate->createPVScalarArray(pvUInt);
|
||||
PVScalarArrayPtr pvLongPtr = pvDataCreate->createPVScalarArray(pvLong);
|
||||
PVScalarArrayPtr pvULongPtr = pvDataCreate->createPVScalarArray(pvULong);
|
||||
PVScalarArrayPtr pvFloatPtr = pvDataCreate->createPVScalarArray(pvFloat);
|
||||
PVScalarArrayPtr pvDoublePtr = pvDataCreate->createPVScalarArray(pvDouble);
|
||||
|
||||
fprintf(fd,"testConvertScalarArray\n");
|
||||
if(debug) fprintf(fd,"\nfromByte\n");
|
||||
size_t length = 4;
|
||||
int8 barray[length];
|
||||
int8 bval = 127;
|
||||
barray[0] = bval;
|
||||
for(size_t i=1; i<length; i++) barray[i] = barray[i-1] + 1;
|
||||
convert->fromByteArray(pvBytePtr,0,length,barray,0);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromByteArray(pvUBytePtr,0,length,barray,0);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromByteArray(pvShortPtr,0,length,barray,0);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromByteArray(pvUShortPtr,0,length,barray,0);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromByteArray(pvIntPtr,0,length,barray,0);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromByteArray(pvUIntPtr,0,length,barray,0);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromByteArray(pvLongPtr,0,length,barray,0);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromByteArray(pvULongPtr,0,length,barray,0);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromByteArray(pvFloatPtr,0,length,barray,0);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromByteArray(pvDoublePtr,0,length,barray,0);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUBytePtr,0, pvFloatPtr,0,length);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUBytePtr,0, pvDoublePtr,0,length);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
fprintf(fd,"fromByte PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromShort\n");
|
||||
int16 sarray[length];
|
||||
int16 sval = 0x7fff;
|
||||
sarray[0] = sval;
|
||||
for(size_t i=1; i<length; i++) sarray[i] = sarray[i-1] + 1;
|
||||
convert->fromShortArray(pvBytePtr,0,length,sarray,0);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromShortArray(pvUBytePtr,0,length,sarray,0);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromShortArray(pvShortPtr,0,length,sarray,0);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromShortArray(pvUShortPtr,0,length,sarray,0);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromShortArray(pvIntPtr,0,length,sarray,0);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromShortArray(pvUIntPtr,0,length,sarray,0);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromShortArray(pvLongPtr,0,length,sarray,0);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromShortArray(pvULongPtr,0,length,sarray,0);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromShortArray(pvFloatPtr,0,length,sarray,0);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromShortArray(pvDoublePtr,0,length,sarray,0);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUShortPtr,0, pvFloatPtr,0,length);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUShortPtr,0, pvDoublePtr,0,length);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
fprintf(fd,"fromShort PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromInt\n");
|
||||
int32 iarray[length];
|
||||
int32 ival = 0x7fffffff;
|
||||
iarray[0] = ival;
|
||||
for(size_t i=1; i<length; i++) iarray[i] = iarray[i-1] + 1;
|
||||
convert->fromIntArray(pvBytePtr,0,length,iarray,0);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromIntArray(pvUBytePtr,0,length,iarray,0);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromIntArray(pvShortPtr,0,length,iarray,0);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromIntArray(pvUShortPtr,0,length,iarray,0);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromIntArray(pvIntPtr,0,length,iarray,0);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromIntArray(pvUIntPtr,0,length,iarray,0);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromIntArray(pvLongPtr,0,length,iarray,0);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromIntArray(pvULongPtr,0,length,iarray,0);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromIntArray(pvFloatPtr,0,length,iarray,0);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromIntArray(pvDoublePtr,0,length,iarray,0);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUIntPtr,0, pvFloatPtr,0,length);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUIntPtr,0, pvDoublePtr,0,length);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
fprintf(fd,"fromInt PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromLong\n");
|
||||
int64 larray[length];
|
||||
int64 lval = 0x7fffffffffffffffLL;
|
||||
larray[0] = lval;
|
||||
for(size_t i=1; i<length; i++) larray[i] = larray[i-1] + 1;
|
||||
convert->fromLongArray(pvBytePtr,0,length,larray,0);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromLongArray(pvUBytePtr,0,length,larray,0);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromLongArray(pvShortPtr,0,length,larray,0);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromLongArray(pvUShortPtr,0,length,larray,0);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromLongArray(pvIntPtr,0,length,larray,0);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromLongArray(pvUIntPtr,0,length,larray,0);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromLongArray(pvLongPtr,0,length,larray,0);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromLongArray(pvULongPtr,0,length,larray,0);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromLongArray(pvFloatPtr,0,length,larray,0);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromLongArray(pvDoublePtr,0,length,larray,0);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvULongPtr,0, pvFloatPtr,0,length);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvULongPtr,0, pvDoublePtr,0,length);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
fprintf(fd,"fromLong PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromUByte\n");
|
||||
uint8 ubarray[length];
|
||||
uint8 ubval = 127;
|
||||
ubarray[0] = ubval;
|
||||
for(size_t i=1; i<length; i++) ubarray[i] = ubarray[i-1] + 1;
|
||||
convert->fromUByteArray(pvBytePtr,0,length,ubarray,0);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvUBytePtr,0,length,ubarray,0);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvShortPtr,0,length,ubarray,0);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvUShortPtr,0,length,ubarray,0);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvIntPtr,0,length,ubarray,0);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvUIntPtr,0,length,ubarray,0);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvLongPtr,0,length,ubarray,0);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvULongPtr,0,length,ubarray,0);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvFloatPtr,0,length,ubarray,0);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvDoublePtr,0,length,ubarray,0);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUBytePtr,0, pvFloatPtr,0,length);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUBytePtr,0, pvDoublePtr,0,length);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
fprintf(fd,"fromUByte PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromUShort\n");
|
||||
uint16 usarray[length];
|
||||
uint16 usval = 0x7fff;
|
||||
usarray[0] = usval;
|
||||
for(size_t i=1; i<length; i++) usarray[i] = usarray[i-1] + 1;
|
||||
convert->fromUShortArray(pvBytePtr,0,length,usarray,0);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromUShortArray(pvUBytePtr,0,length,usarray,0);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromUShortArray(pvShortPtr,0,length,usarray,0);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromUShortArray(pvUShortPtr,0,length,usarray,0);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromUShortArray(pvIntPtr,0,length,usarray,0);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromUShortArray(pvUIntPtr,0,length,usarray,0);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromUShortArray(pvLongPtr,0,length,usarray,0);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromUShortArray(pvULongPtr,0,length,usarray,0);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromUShortArray(pvFloatPtr,0,length,usarray,0);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromUShortArray(pvDoublePtr,0,length,usarray,0);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUShortPtr,0, pvFloatPtr,0,length);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUShortPtr,0, pvDoublePtr,0,length);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
fprintf(fd,"fromUShort PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromUInt\n");
|
||||
uint32 uiarray[length];
|
||||
uint32 uival = 0x7fffffff;
|
||||
uiarray[0] = uival;
|
||||
for(size_t i=1; i<length; i++) uiarray[i] = uiarray[i-1] + 1;
|
||||
convert->fromUIntArray(pvBytePtr,0,length,uiarray,0);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromUIntArray(pvUBytePtr,0,length,uiarray,0);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromUIntArray(pvShortPtr,0,length,uiarray,0);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromUIntArray(pvUShortPtr,0,length,uiarray,0);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromUIntArray(pvIntPtr,0,length,uiarray,0);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromUIntArray(pvUIntPtr,0,length,uiarray,0);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromUIntArray(pvLongPtr,0,length,uiarray,0);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromUIntArray(pvULongPtr,0,length,uiarray,0);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromUIntArray(pvFloatPtr,0,length,uiarray,0);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromUIntArray(pvDoublePtr,0,length,uiarray,0);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUIntPtr,0, pvFloatPtr,0,length);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvUIntPtr,0, pvDoublePtr,0,length);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
fprintf(fd,"fromUInt PASSED\n");
|
||||
|
||||
if(debug) fprintf(fd,"\nfromULong\n");
|
||||
uint64 ularray[length];
|
||||
uint64 ulval = 0x7fffffffffffffffLL;
|
||||
ularray[0] = ulval;
|
||||
for(size_t i=1; i<length; i++) ularray[i] = ularray[i-1] + 1;
|
||||
convert->fromULongArray(pvBytePtr,0,length,ularray,0);
|
||||
builder.clear(); pvBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"byte %s\n",builder.c_str());
|
||||
convert->fromULongArray(pvUBytePtr,0,length,ularray,0);
|
||||
builder.clear(); pvUBytePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ubyte %s\n",builder.c_str());
|
||||
convert->fromULongArray(pvShortPtr,0,length,ularray,0);
|
||||
builder.clear(); pvShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"short %s\n",builder.c_str());
|
||||
convert->fromULongArray(pvUShortPtr,0,length,ularray,0);
|
||||
builder.clear(); pvUShortPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ushort %s\n",builder.c_str());
|
||||
convert->fromULongArray(pvIntPtr,0,length,ularray,0);
|
||||
builder.clear(); pvIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"int %s\n",builder.c_str());
|
||||
convert->fromULongArray(pvUIntPtr,0,length,ularray,0);
|
||||
builder.clear(); pvUIntPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"uint %s\n",builder.c_str());
|
||||
convert->fromULongArray(pvLongPtr,0,length,ularray,0);
|
||||
builder.clear(); pvLongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"long %s\n",builder.c_str());
|
||||
convert->fromULongArray(pvULongPtr,0,length,ularray,0);
|
||||
builder.clear(); pvULongPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"ulong %s\n",builder.c_str());
|
||||
convert->fromULongArray(pvFloatPtr,0,length,ularray,0);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float %s\n",builder.c_str());
|
||||
convert->fromULongArray(pvDoublePtr,0,length,ularray,0);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvULongPtr,0, pvFloatPtr,0,length);
|
||||
builder.clear(); pvFloatPtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"float from unsigned %s\n",builder.c_str());
|
||||
convert->copyScalarArray(pvULongPtr,0, pvDoublePtr,0,length);
|
||||
builder.clear(); pvDoublePtr->toString(&builder);
|
||||
if(debug) fprintf(fd,"double from unsigned %s\n",builder.c_str());
|
||||
fprintf(fd,"fromLong PASSED\n");
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
static void testFromString()
|
||||
{
|
||||
char *fileName = 0;
|
||||
if(argc>1) fileName = argv[1];
|
||||
FILE * fd = stdout;
|
||||
if(fileName!=0 && fileName[0]!=0) {
|
||||
fd = fopen(fileName,"w+");
|
||||
}
|
||||
fieldCreate = getFieldCreate();
|
||||
pvDataCreate = getPVDataCreate();
|
||||
standardField = getStandardField();
|
||||
standardPVField = getStandardPVField();
|
||||
convert = getConvert();
|
||||
testConvertScalar(fd);
|
||||
testConvertScalarArray(fd);
|
||||
fprintf(fd,"THIS NEEDS MANY MORE TESTS AND ASSERTS\n");
|
||||
return(0);
|
||||
StringArray inp(2);
|
||||
|
||||
inp[0] = "0";
|
||||
inp[1] = "1";
|
||||
|
||||
PVScalarArrayPtr A(getPVDataCreate()->createPVScalarArray(pvInt));
|
||||
PVScalarArrayPtr B(getPVDataCreate()->createPVScalarArray(pvString));
|
||||
|
||||
testOk1(2==getConvert()->fromStringArray(A, 0, inp.size(), inp, 0));
|
||||
testOk1(2==getConvert()->fromStringArray(B, 0, inp.size(), inp, 0));
|
||||
|
||||
PVIntArrayPtr Ax(std::tr1::static_pointer_cast<PVIntArray>(A));
|
||||
PVStringArrayPtr Bx(std::tr1::static_pointer_cast<PVStringArray>(B));
|
||||
|
||||
PVIntArray::const_svector Adata(Ax->view());
|
||||
PVStringArray::const_svector Bdata(Bx->view());
|
||||
|
||||
testOk1(inp.size()==Adata.size());
|
||||
if(inp.size()==Adata.size())
|
||||
testOk1(Adata[0]==0 && Adata[1]==1);
|
||||
else
|
||||
testFail("Can't compare");
|
||||
|
||||
testOk1(inp.size()==Bdata.size());
|
||||
if(inp.size()==Bdata.size())
|
||||
testOk1(Bdata[0]=="0" && Bdata[1]=="1");
|
||||
else
|
||||
testFail("Can't compare");
|
||||
}
|
||||
|
||||
MAIN(testConvert)
|
||||
{
|
||||
testPlan(0);
|
||||
testFromString();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include <epicsExit.h>
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/requester.h>
|
||||
#include <pv/executor.h>
|
||||
@@ -23,130 +23,190 @@
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
static bool debug = false;
|
||||
|
||||
static FieldCreatePtr fieldCreate;
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
static StandardFieldPtr standardField;
|
||||
static String builder("");
|
||||
|
||||
static void testScalarCommon(FILE * fd,ScalarType stype,
|
||||
static void testScalarCommon(ScalarType stype,
|
||||
bool isInteger,bool isNumeric,bool isPrimitive)
|
||||
{
|
||||
String builder;
|
||||
ScalarConstPtr pscalar = fieldCreate->createScalar(stype);
|
||||
Type type = pscalar->getType();
|
||||
assert(type==scalar);
|
||||
testOk1(type==scalar);
|
||||
builder.clear();
|
||||
TypeFunc::toString(&builder,type);
|
||||
assert(builder.compare("scalar")==0);
|
||||
testOk1(builder.compare("scalar")==0);
|
||||
ScalarType scalarType = pscalar->getScalarType();
|
||||
assert(scalarType==stype);
|
||||
assert(ScalarTypeFunc::isInteger(scalarType)==isInteger);
|
||||
assert(ScalarTypeFunc::isNumeric(scalarType)==isNumeric);
|
||||
assert(ScalarTypeFunc::isPrimitive(scalarType)==isPrimitive);
|
||||
builder.clear();
|
||||
pscalar->toString(&builder);
|
||||
if(debug) fprintf(fd,"%s\n",builder.c_str());
|
||||
testOk1(scalarType==stype);
|
||||
testOk1(ScalarTypeFunc::isInteger(scalarType)==isInteger);
|
||||
testOk1(ScalarTypeFunc::isNumeric(scalarType)==isNumeric);
|
||||
testOk1(ScalarTypeFunc::isPrimitive(scalarType)==isPrimitive);
|
||||
}
|
||||
|
||||
static void testScalar(FILE * fd) {
|
||||
if(debug) fprintf(fd,"\ntestScalar\n");
|
||||
testScalarCommon(fd,pvBoolean,false,false,true);
|
||||
testScalarCommon(fd,pvByte,true,true,true);
|
||||
testScalarCommon(fd,pvShort,true,true,true);
|
||||
testScalarCommon(fd,pvInt,true,true,true);
|
||||
testScalarCommon(fd,pvLong,true,true,true);
|
||||
testScalarCommon(fd,pvFloat,false,true,true);
|
||||
testScalarCommon(fd,pvDouble,false,true,true);
|
||||
testScalarCommon(fd,pvString,false,false,false);
|
||||
fprintf(fd,"testScalar PASSED\n");
|
||||
static void testScalar() {
|
||||
testDiag("testScalar");
|
||||
testScalarCommon(pvBoolean,false,false,true);
|
||||
testScalarCommon(pvByte,true,true,true);
|
||||
testScalarCommon(pvShort,true,true,true);
|
||||
testScalarCommon(pvInt,true,true,true);
|
||||
testScalarCommon(pvLong,true,true,true);
|
||||
testScalarCommon(pvFloat,false,true,true);
|
||||
testScalarCommon(pvDouble,false,true,true);
|
||||
testScalarCommon(pvString,false,false,false);
|
||||
}
|
||||
|
||||
static void testScalarArrayCommon(FILE * fd,ScalarType stype,
|
||||
static void testScalarArrayCommon(ScalarType stype,
|
||||
bool isInteger,bool isNumeric,bool isPrimitive)
|
||||
{
|
||||
String builder;
|
||||
ScalarArrayConstPtr pscalar = fieldCreate->createScalarArray(stype);
|
||||
Type type = pscalar->getType();
|
||||
assert(type==scalarArray);
|
||||
testOk1(type==scalarArray);
|
||||
builder.clear();
|
||||
TypeFunc::toString(&builder,type);
|
||||
assert(builder.compare("scalarArray")==0);
|
||||
testOk1(builder.compare("scalarArray")==0);
|
||||
ScalarType scalarType = pscalar->getElementType();
|
||||
assert(scalarType==stype);
|
||||
assert(ScalarTypeFunc::isInteger(scalarType)==isInteger);
|
||||
assert(ScalarTypeFunc::isNumeric(scalarType)==isNumeric);
|
||||
assert(ScalarTypeFunc::isPrimitive(scalarType)==isPrimitive);
|
||||
builder.clear();
|
||||
pscalar->toString(&builder);
|
||||
if(debug) fprintf(fd,"%s\n",builder.c_str());
|
||||
testOk1(scalarType==stype);
|
||||
testOk1(ScalarTypeFunc::isInteger(scalarType)==isInteger);
|
||||
testOk1(ScalarTypeFunc::isNumeric(scalarType)==isNumeric);
|
||||
testOk1(ScalarTypeFunc::isPrimitive(scalarType)==isPrimitive);
|
||||
}
|
||||
|
||||
static void testScalarArray(FILE * fd) {
|
||||
if(debug) fprintf(fd,"\ntestScalarArray\n");
|
||||
testScalarArrayCommon(fd,pvBoolean,false,false,true);
|
||||
testScalarArrayCommon(fd,pvByte,true,true,true);
|
||||
testScalarArrayCommon(fd,pvShort,true,true,true);
|
||||
testScalarArrayCommon(fd,pvInt,true,true,true);
|
||||
testScalarArrayCommon(fd,pvLong,true,true,true);
|
||||
testScalarArrayCommon(fd,pvFloat,false,true,true);
|
||||
testScalarArrayCommon(fd,pvDouble,false,true,true);
|
||||
testScalarArrayCommon(fd,pvString,false,false,false);
|
||||
fprintf(fd,"testScalarArray PASSED\n");
|
||||
static void testScalarArray() {
|
||||
testDiag("testScalarArray");
|
||||
testScalarArrayCommon(pvBoolean,false,false,true);
|
||||
testScalarArrayCommon(pvByte,true,true,true);
|
||||
testScalarArrayCommon(pvShort,true,true,true);
|
||||
testScalarArrayCommon(pvInt,true,true,true);
|
||||
testScalarArrayCommon(pvLong,true,true,true);
|
||||
testScalarArrayCommon(pvFloat,false,true,true);
|
||||
testScalarArrayCommon(pvDouble,false,true,true);
|
||||
testScalarArrayCommon(pvString,false,false,false);
|
||||
}
|
||||
|
||||
static void testSimpleStructure(FILE * fd) {
|
||||
if(debug) fprintf(fd,"\ntestSimpleStructure\n");
|
||||
String properties("alarm,timeStamp,display,control,valueAlarm");
|
||||
StructureConstPtr ptop = standardField->scalar(pvDouble,properties);
|
||||
builder.clear();
|
||||
ptop->toString(&builder);
|
||||
if(debug) fprintf(fd,"%s\n",builder.c_str());
|
||||
fprintf(fd,"testSimpleStructure PASSED\n");
|
||||
}
|
||||
|
||||
static StructureConstPtr createPowerSupply() {
|
||||
size_t nfields = 3;
|
||||
String properties("alarm");
|
||||
StringArray names;
|
||||
names.reserve(nfields);
|
||||
FieldConstPtrArray powerSupply;
|
||||
powerSupply.reserve(nfields);
|
||||
names.push_back("voltage");
|
||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
||||
names.push_back("power");
|
||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
||||
names.push_back("current");
|
||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
||||
return fieldCreate->createStructure(names,powerSupply);
|
||||
}
|
||||
|
||||
static void testStructureArray(FILE * fd) {
|
||||
if(debug) fprintf(fd,"\ntestStructureArray\n");
|
||||
String properties("alarm,timeStamp");
|
||||
StructureConstPtr powerSupply = createPowerSupply();
|
||||
StructureConstPtr top = standardField->structureArray(
|
||||
powerSupply,properties);
|
||||
builder.clear();
|
||||
top->toString(&builder);
|
||||
if(debug) fprintf(fd,"%s\n",builder.c_str());
|
||||
fprintf(fd,"testStructureArray PASSED\n");
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
static void testStructure()
|
||||
{
|
||||
char *fileName = 0;
|
||||
if(argc>1) fileName = argv[1];
|
||||
FILE * fd = stdout;
|
||||
if(fileName!=0 && fileName[0]!=0) {
|
||||
fd = fopen(fileName,"w+");
|
||||
}
|
||||
testDiag("testStructure");
|
||||
StringArray names1(2);
|
||||
names1[0] = "innerA";
|
||||
names1[1] = "innerB";
|
||||
FieldConstPtrArray fields1(2);
|
||||
fields1[0] = fieldCreate->createScalar(pvDouble);
|
||||
fields1[1] = fieldCreate->createScalarArray(pvString);
|
||||
|
||||
StructureConstPtr struct1 = fieldCreate->createStructure(names1, fields1);
|
||||
|
||||
testOk1(struct1->getNumberFields()==2);
|
||||
testOk1(struct1->getField("innerA")==fields1[0]);
|
||||
testOk1(struct1->getField("innerB")==fields1[1]);
|
||||
testOk1(struct1->getFieldIndex("innerA")==0);
|
||||
testOk1(struct1->getFieldIndex("innerB")==1);
|
||||
testOk1(struct1->getField(0)==fields1[0]);
|
||||
testOk1(struct1->getField(1)==fields1[1]);
|
||||
testOk1(struct1->getFieldName(0)==names1[0]);
|
||||
testOk1(struct1->getFieldName(1)==names1[1]);
|
||||
|
||||
testOk1(struct1->getID() == Structure::DEFAULT_ID);
|
||||
|
||||
testOk1(fields1 == struct1->getFields()); // vector equality
|
||||
|
||||
StringArray names2(2);
|
||||
names2[0] = "outerA";
|
||||
names2[1] = "outerB";
|
||||
FieldConstPtrArray fields2(2);
|
||||
fields2[0] = fieldCreate->createScalar(pvInt);
|
||||
fields2[1] = std::tr1::static_pointer_cast<const Field>(struct1);
|
||||
|
||||
StructureConstPtr struct2 = fieldCreate->createStructure(names2, fields2);
|
||||
|
||||
testOk1(struct2->getNumberFields()==2); // not recursive
|
||||
testOk1(struct2->getField(1)==fields2[1]);
|
||||
|
||||
StructureArrayConstPtr struct1arr = fieldCreate->createStructureArray(struct1);
|
||||
|
||||
testOk1(struct1arr->getStructure()==struct1);
|
||||
testOk1(struct1arr->getID()=="structure[]");
|
||||
}
|
||||
|
||||
#define testExcept(EXCEPT, CMD) try{ CMD; testFail( "No exception from: " #CMD); } \
|
||||
catch(EXCEPT& e) {testPass("Got expected exception from: " #CMD);} \
|
||||
catch(std::exception& e) {testFail("Got wrong exception %s(%s) from: " #CMD, typeid(e).name(),e.what());} \
|
||||
catch(...) {testFail("Got unknown execption from: " #CMD);}
|
||||
|
||||
static void testError()
|
||||
{
|
||||
testDiag("testError");
|
||||
ScalarType invalidtype = (ScalarType)9999;
|
||||
|
||||
testExcept(std::invalid_argument, ScalarTypeFunc::getScalarType("invalidtype"));
|
||||
|
||||
testExcept(std::invalid_argument, ScalarTypeFunc::elementSize(invalidtype));
|
||||
|
||||
testExcept(std::invalid_argument, ScalarTypeFunc::name(invalidtype));
|
||||
|
||||
testOk1(!ScalarTypeFunc::isInteger(invalidtype));
|
||||
testOk1(!ScalarTypeFunc::isUInteger(invalidtype));
|
||||
testOk1(!ScalarTypeFunc::isNumeric(invalidtype));
|
||||
testOk1(!ScalarTypeFunc::isPrimitive(invalidtype));
|
||||
|
||||
testExcept(std::invalid_argument, fieldCreate->createScalar(invalidtype));
|
||||
testExcept(std::invalid_argument, fieldCreate->createScalarArray(invalidtype));
|
||||
|
||||
StringArray names;
|
||||
FieldConstPtrArray fields(1);
|
||||
|
||||
// fails because names.size()!=fields.size()
|
||||
testExcept(std::invalid_argument, fieldCreate->createStructure(names,fields));
|
||||
|
||||
names.resize(1);;
|
||||
|
||||
// fails because names[0].size()==0
|
||||
testExcept(std::invalid_argument, fieldCreate->createStructure(names,fields));
|
||||
|
||||
names[0] = "hello";
|
||||
|
||||
// fails because fields[0].get()==NULL
|
||||
testExcept(std::invalid_argument, fieldCreate->createStructure(names,fields));
|
||||
|
||||
fields[0] = std::tr1::static_pointer_cast<const Field>(fieldCreate->createScalar(pvDouble));
|
||||
|
||||
testOk1(fieldCreate->createStructure(names,fields).get()!=NULL);
|
||||
}
|
||||
|
||||
static void testMapping()
|
||||
{
|
||||
#define OP(TYPE, ENUM) \
|
||||
testOk1(typeid(ScalarTypeTraits<ENUM>::type)==typeid(TYPE)); \
|
||||
testOk1(ENUM==(ScalarType)ScalarTypeID<TYPE>::value); \
|
||||
testOk1(ENUM==(ScalarType)ScalarTypeID<const TYPE>::value);
|
||||
OP(boolean, pvBoolean)
|
||||
OP(int8, pvByte)
|
||||
OP(int16, pvShort)
|
||||
OP(int32, pvInt)
|
||||
OP(int64, pvLong)
|
||||
OP(uint8, pvUByte)
|
||||
OP(uint16, pvUShort)
|
||||
OP(uint32, pvUInt)
|
||||
OP(uint64, pvULong)
|
||||
OP(float, pvFloat)
|
||||
OP(double, pvDouble)
|
||||
OP(String, pvString)
|
||||
#undef OP
|
||||
|
||||
testOk1((ScalarType)ScalarTypeID<PVField>::value==(ScalarType)-1);
|
||||
}
|
||||
|
||||
MAIN(testIntrospect)
|
||||
{
|
||||
testPlan(161);
|
||||
fieldCreate = getFieldCreate();
|
||||
pvDataCreate = getPVDataCreate();
|
||||
standardField = getStandardField();
|
||||
testScalar(fd);
|
||||
testScalarArray(fd);
|
||||
testSimpleStructure(fd);
|
||||
testStructureArray(fd);
|
||||
return(0);
|
||||
testScalar();
|
||||
testScalarArray();
|
||||
testStructure();
|
||||
testError();
|
||||
testMapping();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
@@ -66,9 +66,10 @@ int main(int, char **)
|
||||
pvStructure = standardPVField->scalarArray(pvDouble,"alarm,timeStamp");
|
||||
std::cout << *pvStructure << std::endl;
|
||||
|
||||
double values[] = { 1.1, 2.2, 3.3 };
|
||||
PVDoubleArray::svector values(3);
|
||||
values[0] = 1.1; values[1] = 2.2; values[2] = 3.3;
|
||||
PVDoubleArrayPtr darray = std::tr1::dynamic_pointer_cast<PVDoubleArray>(pvStructure->getScalarArrayField("value", pvDouble));
|
||||
darray->put(0, 3, values, 0);
|
||||
darray->replace(freeze(values));
|
||||
std::cout << *darray << std::endl;
|
||||
std::cout << format::array_at(1) << *darray << std::endl;
|
||||
|
||||
@@ -76,14 +77,13 @@ int main(int, char **)
|
||||
StructureConstPtr structure = standardField->scalar(pvDouble, "alarm,timeStamp");
|
||||
pvStructure = standardPVField->structureArray(structure,"alarm,timeStamp");
|
||||
size_t num = 2;
|
||||
PVStructurePtrArray pvStructures;
|
||||
pvStructures.reserve(num);
|
||||
PVStructureArray::svector pvStructures(num);
|
||||
for(size_t i=0; i<num; i++) {
|
||||
pvStructures.push_back(
|
||||
pvDataCreate->createPVStructure(structure));
|
||||
pvStructures[i]=
|
||||
pvDataCreate->createPVStructure(structure);
|
||||
}
|
||||
PVStructureArrayPtr pvStructureArray = pvStructure->getStructureArrayField("value");
|
||||
pvStructureArray->put(0, num, pvStructures, 0);
|
||||
pvStructureArray->replace(freeze(pvStructures));
|
||||
std::cout << *pvStructure << std::endl;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include <epicsExit.h>
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/requester.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
@@ -25,352 +27,165 @@
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
static bool debug = false;
|
||||
namespace {
|
||||
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
static StandardPVFieldPtr standardPVField = getStandardPVField();
|
||||
static ConvertPtr convert = getConvert();
|
||||
static String builder;
|
||||
static String alarmTimeStamp("alarm,timeStamp");
|
||||
static String alarmTimeStampValueAlarm("alarm,timeStamp,valueAlarm");
|
||||
static String allProperties("alarm,timeStamp,display,control,valueAlarm");
|
||||
static FILE * fd = NULL;
|
||||
static size_t length = 4;
|
||||
|
||||
static void byteArray()
|
||||
static void testFactory()
|
||||
{
|
||||
if(debug) fprintf(fd,"\nbyteArray\n");
|
||||
PVScalarArrayPtr pvScalarArray = pvDataCreate->createPVScalarArray(pvByte);;
|
||||
PVByteArrayPtr pvByteArray = static_pointer_cast<PVByteArray>(pvScalarArray);
|
||||
ByteArray value;
|
||||
value.reserve(length);
|
||||
int8 xxx = 0x7f;
|
||||
for(size_t i = 0; i<length; i++) value.push_back(xxx++);
|
||||
pvByteArray->put(0,length,value,0);
|
||||
builder.clear();
|
||||
pvByteArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"put\n%s\n",builder.c_str());
|
||||
convert->fromByteArray(pvScalarArray,0,length,value,0);
|
||||
builder.clear();
|
||||
pvByteArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"convert\n%s\n",builder.c_str());
|
||||
ByteArrayData data;
|
||||
pvByteArray->get(0,length,data);
|
||||
ByteArray_iterator iter = data.data.begin();
|
||||
if(debug) fprintf(fd,"iter [");
|
||||
for(iter=data.data.begin();iter!=data.data.end();++iter) {
|
||||
if(debug) fprintf(fd,"%d ",*iter);
|
||||
testDiag("Check array creation");
|
||||
|
||||
for(ScalarType e=pvBoolean; e<=pvString; e=(ScalarType)(1+(int)e))
|
||||
{
|
||||
testDiag("Check type %s", ScalarTypeFunc::name(e));
|
||||
PVScalarArrayPtr arr = getPVDataCreate()->createPVScalarArray(e);
|
||||
testOk1(arr.get()!=NULL);
|
||||
if(!arr.get())
|
||||
continue;
|
||||
testOk1(arr->getScalarArray()->getElementType()==e);
|
||||
testOk1(arr->getLength()==0);
|
||||
arr->setLength(10);
|
||||
testOk1(arr->getLength()==10);
|
||||
testOk1(arr->getCapacity()>=10);
|
||||
arr->setLength(0);
|
||||
testOk1(arr->getLength()==0);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"raw [");
|
||||
int8 * pdata = get(data.data);
|
||||
for(size_t i=0; i<length; i++) {
|
||||
int val = pdata[i];
|
||||
if(debug) fprintf(fd,"%d ",val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"direct[");
|
||||
for(size_t i=0; i<length; i++) {
|
||||
int val = data.data[i];
|
||||
if(debug) fprintf(fd,"%d ",val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
fprintf(fd,"byteArray PASSED\n");
|
||||
}
|
||||
|
||||
static void ubyteArray()
|
||||
template<typename PVT>
|
||||
bool hasUniqueVector(const typename PVT::shared_pointer& pv)
|
||||
{
|
||||
if(debug) fprintf(fd,"\nubyteArray\n");
|
||||
PVScalarArrayPtr pvScalarArray = pvDataCreate->createPVScalarArray(pvUByte);;
|
||||
PVUByteArrayPtr pvUByteArray = static_pointer_cast<PVUByteArray>(pvScalarArray);
|
||||
UByteArray value;
|
||||
value.reserve(length);
|
||||
uint8 xxx = 0x7f;
|
||||
for(size_t i = 0; i<length; i++) value.push_back(xxx++);
|
||||
pvUByteArray->put(0,length,value,0);
|
||||
builder.clear();
|
||||
pvUByteArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"put\n%s\n",builder.c_str());
|
||||
convert->fromUByteArray(pvScalarArray,0,length,value,0);
|
||||
builder.clear();
|
||||
pvUByteArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"convert\n%s\n",builder.c_str());
|
||||
UByteArrayData data;
|
||||
pvUByteArray->get(0,length,data);
|
||||
UByteArray_iterator iter = data.data.begin();
|
||||
if(debug) fprintf(fd,"iter [");
|
||||
for(iter=data.data.begin();iter!=data.data.end();++iter) {
|
||||
if(debug) fprintf(fd,"%u ",*iter);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"raw [");
|
||||
uint8 * pdata = get(data.data);
|
||||
for(size_t i=0; i<length; i++) {
|
||||
unsigned int val = pdata[i];
|
||||
if(debug) fprintf(fd,"%d ",val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"direct[");
|
||||
for(size_t i=0; i<length; i++) {
|
||||
unsigned int val = data.data[i];
|
||||
if(debug) fprintf(fd,"%d ",val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
fprintf(fd,"ubyteArray PASSED\n");
|
||||
typename PVT::const_svector data;
|
||||
pv->swap(data);
|
||||
bool ret = data.unique();
|
||||
pv->swap(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void longArray()
|
||||
template<typename PVT>
|
||||
struct basicTestData {
|
||||
static inline void fill(typename PVT::svector& data) {
|
||||
data.resize(100);
|
||||
for(size_t i=0; i<data.size(); i++)
|
||||
{
|
||||
data[i] = 10*i;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct basicTestData<PVStringArray> {
|
||||
static inline void fill(PVStringArray::svector& data) {
|
||||
PVIntArray::svector idata;
|
||||
basicTestData<PVIntArray>::fill(idata);
|
||||
data.resize(idata.size());
|
||||
castUnsafeV(data.size(), pvString, data.data(), pvInt, idata.data());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PVT>
|
||||
static void testBasic()
|
||||
{
|
||||
if(debug) fprintf(fd,"\nlongArray\n");
|
||||
PVScalarArrayPtr pvScalarArray = pvDataCreate->createPVScalarArray(pvLong);;
|
||||
PVLongArrayPtr pvLongArray = static_pointer_cast<PVLongArray>(pvScalarArray);
|
||||
LongArray value;
|
||||
value.reserve(length);
|
||||
int64 xxx = 0x7fffffffffffffffLL;
|
||||
for(size_t i = 0; i<length; i++) value.push_back(xxx++);
|
||||
pvLongArray->put(0,length,value,0);
|
||||
builder.clear();
|
||||
pvLongArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"put\n%s\n",builder.c_str());
|
||||
convert->fromLongArray(pvScalarArray,0,length,value,0);
|
||||
builder.clear();
|
||||
pvLongArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"convert\n%s\n",builder.c_str());
|
||||
LongArrayData data;
|
||||
pvLongArray->get(0,length,data);
|
||||
LongArray_iterator iter = data.data.begin();
|
||||
if(debug) fprintf(fd,"iter [");
|
||||
for(iter=data.data.begin();iter!=data.data.end();++iter) {
|
||||
if(debug) fprintf(fd,"%lli ",(long long)*iter);
|
||||
testDiag("Check basic array operations for %s", typeid(PVT).name());
|
||||
|
||||
typename PVT::shared_pointer arr1 = static_pointer_cast<PVT>(getPVDataCreate()->createPVScalarArray(PVT::typeCode));
|
||||
typename PVT::shared_pointer arr2 = static_pointer_cast<PVT>(getPVDataCreate()->createPVScalarArray(PVT::typeCode));
|
||||
|
||||
testOk1(*arr1==*arr2);
|
||||
testOk1(*arr1==*arr1);
|
||||
testOk1(*arr1->getScalarArray()==*arr2->getScalarArray());
|
||||
|
||||
typename PVT::svector data;
|
||||
data.reserve(200);
|
||||
basicTestData<PVT>::fill(data);
|
||||
|
||||
typename PVT::const_svector cdata(freeze(data));
|
||||
|
||||
testOk1(cdata.unique());
|
||||
arr1->replace(cdata);
|
||||
testOk1(!cdata.unique());
|
||||
|
||||
{
|
||||
typename PVT::const_svector avoid;
|
||||
arr1->PVScalarArray::getAs<typename PVT::value_type>(avoid);
|
||||
testOk1(avoid.data()==cdata.data());
|
||||
testOk1(avoid.data()==arr1->view().data());
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"raw [");
|
||||
int64 * pdata = get(data.data);
|
||||
for(size_t i=0; i<length; i++) {
|
||||
int64 val = pdata[i];
|
||||
if(debug) fprintf(fd,"%lli ",(long long)val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"direct[");
|
||||
for(size_t i=0; i<length; i++) {
|
||||
int64 val = data.data[i];
|
||||
if(debug) fprintf(fd,"%lli ",(long long)val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
fprintf(fd,"longArray PASSED\n");
|
||||
|
||||
testOk1(arr1->getLength()==cdata.size());
|
||||
|
||||
testOk1(*arr1!=*arr2);
|
||||
|
||||
cdata.clear();
|
||||
|
||||
testOk1(hasUniqueVector<PVT>(arr1));
|
||||
|
||||
arr2->assign(*arr1);
|
||||
|
||||
testOk1(*arr1==*arr2);
|
||||
testOk1(!hasUniqueVector<PVT>(arr1));
|
||||
|
||||
arr2->swap(cdata);
|
||||
arr2->postPut();
|
||||
|
||||
testOk1(arr2->getLength()==0);
|
||||
testOk1(cdata.size()==arr1->getLength());
|
||||
|
||||
PVIntArray::const_svector idata;
|
||||
arr1->PVScalarArray::getAs<int32>(idata);
|
||||
|
||||
testOk1(idata.at(1)==10);
|
||||
|
||||
PVIntArray::svector wdata(thaw(idata));
|
||||
|
||||
wdata.at(1) = 42;
|
||||
|
||||
idata = freeze(wdata);
|
||||
|
||||
arr1->PVScalarArray::putFrom<int32>(idata);
|
||||
|
||||
testOk1(castUnsafe<PVIntArray::value_type>(arr1->view()[1])==42);
|
||||
}
|
||||
|
||||
static void ulongArray()
|
||||
static void testShare()
|
||||
{
|
||||
if(debug) fprintf(fd,"\nulongArray\n");
|
||||
PVScalarArrayPtr pvScalarArray = pvDataCreate->createPVScalarArray(pvULong);;
|
||||
PVULongArrayPtr pvULongArray = static_pointer_cast<PVULongArray>(pvScalarArray);
|
||||
ULongArray value;
|
||||
value.reserve(length);
|
||||
uint64 xxx = 0x7fffffffffffffffLL;
|
||||
for(size_t i = 0; i<length; i++) value.push_back(xxx++);
|
||||
pvULongArray->put(0,length,value,0);
|
||||
builder.clear();
|
||||
pvULongArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"put\n%s\n",builder.c_str());
|
||||
convert->fromULongArray(pvScalarArray,0,length,value,0);
|
||||
builder.clear();
|
||||
pvULongArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"convert\n%s\n",builder.c_str());
|
||||
ULongArrayData data;
|
||||
pvULongArray->get(0,length,data);
|
||||
ULongArray_iterator iter = data.data.begin();
|
||||
if(debug) fprintf(fd,"iter [");
|
||||
for(iter=data.data.begin();iter!=data.data.end();++iter) {
|
||||
if(debug) fprintf(fd,"%llu ",(long long unsigned)*iter);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"raw [");
|
||||
uint64 * pdata = get(data.data);
|
||||
for(size_t i=0; i<length; i++) {
|
||||
uint64 val = pdata[i];
|
||||
if(debug) fprintf(fd,"%llu ",(long long unsigned)val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"direct[");
|
||||
for(size_t i=0; i<length; i++) {
|
||||
uint64 val = data.data[i];
|
||||
if(debug) fprintf(fd,"%llu ",(long long unsigned)val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
fprintf(fd,"ulongArray PASSED\n");
|
||||
testDiag("Check array data sharing");
|
||||
|
||||
PVIntArrayPtr iarr = static_pointer_cast<PVIntArray>(getPVDataCreate()->createPVScalarArray(pvInt));
|
||||
PVStringArrayPtr sarr = static_pointer_cast<PVStringArray>(getPVDataCreate()->createPVScalarArray(pvString));
|
||||
|
||||
PVIntArray::const_svector idata(4, 1);
|
||||
|
||||
sarr->PVScalarArray::putFrom<int32>(idata); // copy and convert
|
||||
|
||||
testOk1(idata.unique());
|
||||
|
||||
iarr->PVScalarArray::putFrom<int32>(idata); // take a reference
|
||||
|
||||
testOk1(!idata.unique());
|
||||
|
||||
idata.clear();
|
||||
PVIntArray::const_svector cdata;
|
||||
|
||||
sarr->PVScalarArray::getAs<int32>(cdata); // copy and convert
|
||||
|
||||
testOk1(cdata.unique());
|
||||
|
||||
iarr->PVScalarArray::getAs<int32>(cdata); // take a reference
|
||||
|
||||
testOk1(!cdata.unique());
|
||||
}
|
||||
|
||||
static void floatArray()
|
||||
{
|
||||
if(debug) fprintf(fd,"\nfloatArray\n");
|
||||
PVScalarArrayPtr pvScalarArray = pvDataCreate->createPVScalarArray(pvFloat);;
|
||||
PVFloatArrayPtr pvFloatArray = static_pointer_cast<PVFloatArray>(pvScalarArray);
|
||||
FloatArray value;
|
||||
value.reserve(length);
|
||||
for(size_t i = 0; i<length; i++) value.push_back(10.0*i);
|
||||
pvFloatArray->put(0,length,value,0);
|
||||
builder.clear();
|
||||
pvFloatArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"put\n%s\n",builder.c_str());
|
||||
convert->fromFloatArray(pvScalarArray,0,length,value,0);
|
||||
builder.clear();
|
||||
pvFloatArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"convert\n%s\n",builder.c_str());
|
||||
FloatArrayData data;
|
||||
pvFloatArray->get(0,length,data);
|
||||
FloatArray_iterator iter = data.data.begin();
|
||||
if(debug) fprintf(fd,"iter [");
|
||||
for(iter=data.data.begin();iter!=data.data.end();++iter) {
|
||||
if(debug) fprintf(fd,"%f ",*iter);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"raw [");
|
||||
float * pdata = get(data.data);
|
||||
for(size_t i=0; i<length; i++) {
|
||||
float val = pdata[i];
|
||||
if(debug) fprintf(fd,"%f ",val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"direct[");
|
||||
for(size_t i=0; i<length; i++) {
|
||||
float val = data.data[i];
|
||||
if(debug) fprintf(fd,"%f ",val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
fprintf(fd,"floatArray PASSED\n");
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
static void doubleArray()
|
||||
MAIN(testPVScalarArray)
|
||||
{
|
||||
if(debug) fprintf(fd,"\ndoubleArray\n");
|
||||
PVScalarArrayPtr pvScalarArray = pvDataCreate->createPVScalarArray(pvDouble);;
|
||||
PVDoubleArrayPtr pvDoubleArray = static_pointer_cast<PVDoubleArray>(pvScalarArray);
|
||||
DoubleArray value;
|
||||
value.reserve(length);
|
||||
for(size_t i = 0; i<length; i++) value.push_back(10.0*i);
|
||||
pvDoubleArray->put(0,length,value,0);
|
||||
builder.clear();
|
||||
pvDoubleArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"put\n%s\n",builder.c_str());
|
||||
convert->fromDoubleArray(pvScalarArray,0,length,value,0);
|
||||
builder.clear();
|
||||
pvDoubleArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"convert\n%s\n",builder.c_str());
|
||||
DoubleArrayData data;
|
||||
pvDoubleArray->get(0,length,data);
|
||||
DoubleArray_iterator iter = data.data.begin();
|
||||
if(debug) fprintf(fd,"iter [");
|
||||
for(iter=data.data.begin();iter!=data.data.end();++iter) {
|
||||
if(debug) fprintf(fd,"%lf ",*iter);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"raw [");
|
||||
double * pdata = get(data.data);
|
||||
for(size_t i=0; i<length; i++) {
|
||||
double val = pdata[i];
|
||||
if(debug) fprintf(fd,"%lf ",val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"direct[");
|
||||
for(size_t i=0; i<length; i++) {
|
||||
double val = data.data[i];
|
||||
if(debug) fprintf(fd,"%lf ",val);
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
fprintf(fd,"doubleArray PASSED\n");
|
||||
testPlan(156);
|
||||
testFactory();
|
||||
testBasic<PVByteArray>();
|
||||
testBasic<PVUByteArray>();
|
||||
testBasic<PVIntArray>();
|
||||
testBasic<PVDoubleArray>();
|
||||
testBasic<PVStringArray>();
|
||||
testShare();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
static void stringArray()
|
||||
{
|
||||
if(debug) fprintf(fd,"\nstringArray\n");
|
||||
PVScalarArrayPtr pvScalarArray = pvDataCreate->createPVScalarArray(pvString);;
|
||||
PVStringArrayPtr pvStringArray = static_pointer_cast<PVStringArray>(pvScalarArray);
|
||||
StringArray value;
|
||||
value.reserve(length);
|
||||
for(size_t i = 0; i<length; i++) {
|
||||
char val[20];
|
||||
sprintf(val,"value%d",(int)i);
|
||||
value.push_back(val);
|
||||
}
|
||||
pvStringArray->put(0,length,value,0);
|
||||
builder.clear();
|
||||
pvStringArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"put\n%s\n",builder.c_str());
|
||||
convert->fromStringArray(pvScalarArray,0,length,value,0);
|
||||
builder.clear();
|
||||
pvStringArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"convert\n%s\n",builder.c_str());
|
||||
StringArrayData data;
|
||||
pvStringArray->get(0,length,data);
|
||||
StringArray_iterator iter = data.data.begin();
|
||||
if(debug) fprintf(fd,"iter [");
|
||||
for(iter=data.data.begin();iter!=data.data.end();++iter) {
|
||||
String val = *iter;
|
||||
if(debug) fprintf(fd,"%s ",val.c_str());
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"raw [");
|
||||
String* pdata = get(data.data);
|
||||
for(size_t i=0; i<length; i++) {
|
||||
String val = pdata[i];
|
||||
if(debug) fprintf(fd,"%s ",val.c_str());
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
if(debug) fprintf(fd,"direct[");
|
||||
for(size_t i=0; i<length; i++) {
|
||||
String val = data.data[i];
|
||||
if(debug) fprintf(fd,"%s ",val.c_str());
|
||||
}
|
||||
if(debug) fprintf(fd,"]\n");
|
||||
fprintf(fd,"stringArray PASSED\n");
|
||||
}
|
||||
|
||||
static void shareArray()
|
||||
{
|
||||
if(debug) fprintf(fd,"\nshareArray\n");
|
||||
PVScalarArrayPtr pvScalarArray = pvDataCreate->createPVScalarArray(pvDouble);;
|
||||
PVDoubleArrayPtr pvDoubleArray = static_pointer_cast<PVDoubleArray>(pvScalarArray);
|
||||
DoubleArray value;
|
||||
value.reserve(length);
|
||||
for(size_t i = 0; i<length; i++) value.push_back(10.0*i);
|
||||
pvDoubleArray->put(0,length,value,0);
|
||||
PVDoubleArrayPtr pvShareArray = static_pointer_cast<PVDoubleArray>(
|
||||
pvDataCreate->createPVScalarArray(pvDouble));
|
||||
pvShareArray->shareData(
|
||||
pvDoubleArray->getSharedVector(),
|
||||
pvDoubleArray->getCapacity(),
|
||||
pvDoubleArray->getLength());
|
||||
printf("pvDoubleArray->get() %p pvShareArray->get() %p\n",pvDoubleArray->get(),pvShareArray->get());
|
||||
printf("pvDoubleArray->getVector() %p pvShareArray->getVector() %p\n",
|
||||
&(pvDoubleArray->getVector()),&(pvShareArray->getVector()));
|
||||
printf("pvDoubleArray->getSharedVector() %p pvShareArray->getSharedVector() %p\n",
|
||||
&(pvDoubleArray->getSharedVector()),&(pvShareArray->getSharedVector()));
|
||||
assert(pvDoubleArray->get()==pvShareArray->get());
|
||||
builder.clear();
|
||||
pvShareArray->toString(&builder);
|
||||
if(debug) fprintf(fd,"pvShare\n%s\n",builder.c_str());
|
||||
fprintf(fd,"shareArray PASSED\n");
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
char *fileName = 0;
|
||||
if(argc>1) fileName = argv[1];
|
||||
fd = stdout;
|
||||
if(fileName!=0 && fileName[0]!=0) {
|
||||
fd = fopen(fileName,"w+");
|
||||
}
|
||||
byteArray();
|
||||
ubyteArray();
|
||||
longArray();
|
||||
ulongArray();
|
||||
floatArray();
|
||||
doubleArray();
|
||||
stringArray();
|
||||
shareArray();
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,101 +22,138 @@
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
static bool debug = false;
|
||||
using namespace epics::pvData;
|
||||
|
||||
static FieldCreatePtr fieldCreate;
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
static StandardFieldPtr standardField;
|
||||
static StandardPVFieldPtr standardPVField;
|
||||
static ConvertPtr convert;
|
||||
static String buffer;
|
||||
|
||||
static void testPVStructureArray(FILE * fd) {
|
||||
if(debug) fprintf(fd,"/ntestPVStructureArray\n");
|
||||
StructureArrayConstPtr alarm(
|
||||
fieldCreate->createStructureArray(standardField->alarm()));
|
||||
PVStructureArrayPtr pvAlarmStructure(
|
||||
pvDataCreate->createPVStructureArray(alarm));
|
||||
PVStructurePtrArray palarms;
|
||||
size_t na=2;
|
||||
palarms.reserve(na);
|
||||
for(size_t i=0; i<na; i++) {
|
||||
palarms.push_back(
|
||||
pvDataCreate->createPVStructure(standardField->alarm()));
|
||||
}
|
||||
pvAlarmStructure->put(0,2,palarms,0);
|
||||
buffer.clear();
|
||||
pvAlarmStructure->toString(&buffer);
|
||||
if(debug) fprintf(fd,"pvAlarmStructure\n%s\n",buffer.c_str());
|
||||
PVStructureArrayPtr copy(pvDataCreate->createPVStructureArray(alarm));
|
||||
convert->copyStructureArray(pvAlarmStructure,copy);
|
||||
buffer.clear();
|
||||
copy->toString(&buffer);
|
||||
if(debug) fprintf(fd,"copy\n%s\n",buffer.c_str());
|
||||
fprintf(fd,"testPVStructureArray PASSED\n");
|
||||
}
|
||||
|
||||
static StructureConstPtr getPowerSupplyStructure() {
|
||||
String properties("alarm");
|
||||
FieldConstPtrArray fields;
|
||||
StringArray fieldNames;
|
||||
fields.reserve(3);
|
||||
fieldNames.reserve(3);
|
||||
fieldNames.push_back("voltage");
|
||||
fieldNames.push_back("power");
|
||||
fieldNames.push_back("current");
|
||||
fields.push_back(standardField->scalar(pvDouble,properties));
|
||||
fields.push_back(standardField->scalar(pvDouble,properties));
|
||||
fields.push_back(standardField->scalar(pvDouble,properties));
|
||||
StructureConstPtr structure = fieldCreate->createStructure(
|
||||
"powerSupply_t",fieldNames,fields);
|
||||
return structure;
|
||||
}
|
||||
|
||||
static void testPowerSupplyArray(FILE * fd) {
|
||||
if(debug) fprintf(fd,"/ntestPowerSupplyArray\n");
|
||||
PVStructurePtr powerSupplyArrayStruct = standardPVField->structureArray(
|
||||
getPowerSupplyStructure(),String("alarm,timeStamp"));
|
||||
PVStructureArrayPtr powerSupplyArray =
|
||||
powerSupplyArrayStruct->getStructureArrayField(String("value"));
|
||||
assert(powerSupplyArray.get()!=NULL);
|
||||
int offset = powerSupplyArray->append(5);
|
||||
if(debug) fprintf(fd,"offset %d\n",offset);
|
||||
buffer.clear();
|
||||
powerSupplyArrayStruct->toString(&buffer);
|
||||
if(debug) fprintf(fd,"after append 5\n%s\n",buffer.c_str());
|
||||
powerSupplyArray->remove(0,2);
|
||||
buffer.clear();
|
||||
powerSupplyArrayStruct->toString(&buffer);
|
||||
if(debug) fprintf(fd,"after remove(0,2)\n%s\n",buffer.c_str());
|
||||
powerSupplyArray->remove(2,1);
|
||||
buffer.clear();
|
||||
powerSupplyArrayStruct->toString(&buffer);
|
||||
if(debug) fprintf(fd,"after remove 2,1%s\n",buffer.c_str());
|
||||
powerSupplyArray->compress();
|
||||
buffer.clear();
|
||||
powerSupplyArrayStruct->toString(&buffer);
|
||||
if(debug) fprintf(fd,"after compress%s\n",buffer.c_str());
|
||||
fprintf(fd,"testPowerSupplyArray PASSED\n");
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
static void testBasic()
|
||||
{
|
||||
char *fileName = 0;
|
||||
if(argc>1) fileName = argv[1];
|
||||
FILE * fd = stdout;
|
||||
if(fileName!=0 && fileName[0]!=0) {
|
||||
fd = fopen(fileName,"w+");
|
||||
}
|
||||
testDiag("Basic structure array ops");
|
||||
|
||||
StructureArrayConstPtr alarmtype(
|
||||
fieldCreate->createStructureArray(standardField->alarm()));
|
||||
|
||||
PVStructureArrayPtr alarmarr(pvDataCreate->createPVStructureArray(alarmtype));
|
||||
|
||||
testOk1(alarmarr->getLength()==0);
|
||||
|
||||
alarmarr->setLength(5);
|
||||
|
||||
testOk1(alarmarr->getLength()==5);
|
||||
|
||||
PVStructureArray::const_svector aview = alarmarr->view();
|
||||
|
||||
testOk1(aview.size()==5);
|
||||
testOk1(aview[4].get()==NULL);
|
||||
|
||||
alarmarr->append(2);
|
||||
|
||||
testOk1(alarmarr->getLength()==7);
|
||||
|
||||
aview = alarmarr->view();
|
||||
|
||||
testOk1(aview[4].get()==NULL);
|
||||
testOk1(aview[5].get()!=NULL);
|
||||
testOk1(aview[6].get()!=NULL);
|
||||
}
|
||||
|
||||
static void testCompress()
|
||||
{
|
||||
testDiag("Test structure array compress");
|
||||
|
||||
StructureArrayConstPtr alarmtype(
|
||||
fieldCreate->createStructureArray(standardField->alarm()));
|
||||
|
||||
PVStructureArrayPtr alarmarr(pvDataCreate->createPVStructureArray(alarmtype));
|
||||
|
||||
alarmarr->setLength(5);
|
||||
|
||||
testOk1(alarmarr->getLength()==5);
|
||||
|
||||
alarmarr->compress();
|
||||
|
||||
testOk1(alarmarr->getLength()==0);
|
||||
|
||||
alarmarr->setLength(4);
|
||||
|
||||
testOk1(alarmarr->getLength()==4);
|
||||
|
||||
PVStructureArray::svector contents(10);
|
||||
|
||||
contents[2] = pvDataCreate->createPVStructure(standardField->alarm());
|
||||
contents[4] = pvDataCreate->createPVStructure(standardField->alarm());
|
||||
contents[5] = pvDataCreate->createPVStructure(standardField->alarm());
|
||||
contents[8] = pvDataCreate->createPVStructure(standardField->alarm());
|
||||
|
||||
PVStructureArray::const_svector scont(freeze(contents));
|
||||
|
||||
alarmarr->replace(scont);
|
||||
|
||||
testOk1(!scont.unique());
|
||||
testOk1(alarmarr->getLength()==10);
|
||||
|
||||
alarmarr->compress();
|
||||
|
||||
testOk1(scont.unique()); // a realloc happened
|
||||
testOk1(alarmarr->getLength()==4);
|
||||
|
||||
PVStructureArray::svector compressed(alarmarr->reuse());
|
||||
|
||||
testOk1(scont[2]==compressed[0]);
|
||||
testOk1(scont[4]==compressed[1]);
|
||||
testOk1(scont[5]==compressed[2]);
|
||||
testOk1(scont[8]==compressed[3]);
|
||||
}
|
||||
|
||||
static void testRemove()
|
||||
{
|
||||
testDiag("Test structure array remove");
|
||||
|
||||
PVStructureArray::svector contents(10);
|
||||
|
||||
for(size_t i=0; i<contents.size(); i++)
|
||||
contents[i] = pvDataCreate->createPVStructure(standardField->alarm());
|
||||
|
||||
StructureArrayConstPtr alarmtype(
|
||||
fieldCreate->createStructureArray(standardField->alarm()));
|
||||
PVStructureArrayPtr alarmarr(pvDataCreate->createPVStructureArray(alarmtype));
|
||||
|
||||
PVStructureArray::const_svector scont(freeze(contents));
|
||||
|
||||
alarmarr->replace(scont);
|
||||
|
||||
alarmarr->remove(0, 10); // all
|
||||
|
||||
testOk1(alarmarr->getLength()==0);
|
||||
|
||||
alarmarr->replace(scont);
|
||||
|
||||
alarmarr->remove(1, 1);
|
||||
|
||||
PVStructureArray::const_svector check(alarmarr->view());
|
||||
|
||||
testOk1(scont[0]==check[0]);
|
||||
testOk1(scont[2]==check[1]);
|
||||
testOk1(scont[3]==check[2]);
|
||||
}
|
||||
|
||||
MAIN(testPVStructureArray)
|
||||
{
|
||||
testPlan(0);
|
||||
testDiag("Testing structure array handling");
|
||||
fieldCreate = getFieldCreate();
|
||||
pvDataCreate = getPVDataCreate();
|
||||
standardField = getStandardField();
|
||||
standardPVField = getStandardPVField();
|
||||
convert = getConvert();
|
||||
testPVStructureArray(fd);
|
||||
testPowerSupplyArray(fd);
|
||||
return(0);
|
||||
testBasic();
|
||||
testCompress();
|
||||
testRemove();
|
||||
return testDone();
|
||||
}
|
||||
|
||||
|
||||
@@ -70,14 +70,13 @@ int main(int, char **)
|
||||
StructureConstPtr structure = standardField->scalar(pvDouble, "alarm,timeStamp");
|
||||
pvStructure = standardPVField->structureArray(structure,"alarm,timeStamp");
|
||||
size_t num = 2;
|
||||
PVStructurePtrArray pvStructures;
|
||||
pvStructures.reserve(num);
|
||||
PVStructureArray::svector pvStructures(num);
|
||||
for(size_t i=0; i<num; i++) {
|
||||
pvStructures.push_back(
|
||||
pvDataCreate->createPVStructure(structure));
|
||||
pvStructures[i]=
|
||||
pvDataCreate->createPVStructure(structure);
|
||||
}
|
||||
PVStructureArrayPtr pvStructureArray = pvStructure->getStructureArrayField("value");
|
||||
pvStructureArray->put(0, num, pvStructures, 0);
|
||||
pvStructureArray->replace(freeze(pvStructures));
|
||||
builder.clear();
|
||||
pvStructure->toString(&builder);
|
||||
print("structureArrayTest");
|
||||
|
||||
Reference in New Issue
Block a user