/* pvData.h */ /** * 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 mrk */ #ifndef PVDATA_H #define PVDATA_H #ifdef _WIN32 #define NOMINMAX #endif #if defined(__GNUC__) && !(defined(__vxworks) && !defined(_WRS_VXWORKS_MAJOR)) #define USAGE_DEPRECATED __attribute__((deprecated)) #define USAGE_ERROR(MSG) __attribute__((error(MSG))) #else #define USAGE_DEPRECATED #define USAGE_ERROR(MSG) { throw std::runtime_error(MSG); } #endif #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__vxworks) && !defined(_WRS_VXWORKS_MAJOR) typedef class std::ios std::ios_base; #endif namespace epics { namespace pvData { namespace format { struct indent_level { long level; indent_level(long l) : level(l) {} }; inline long& indent_value(std::ios_base& ios) { static int indent_index = std::ios_base::xalloc(); return ios.iword(indent_index); } epicsShareExtern std::ostream& operator<<(std::ostream& os, indent_level const& indent); struct indent_scope { long saved_level; std::ios_base& stream; indent_scope(std::ios_base& ios) : stream(ios) { long& l = indent_value(ios); saved_level = l; l = saved_level + 1; } ~indent_scope() { indent_value(stream) = saved_level; } }; struct indent { }; epicsShareExtern std::ostream& operator<<(std::ostream& os, indent const&); struct array_at { std::size_t index; array_at(std::size_t ix) : index(ix) {} }; struct array_at_internal { std::size_t index; std::ostream& stream; array_at_internal(std::size_t ix, std::ostream& str) : index(ix), stream(str) {} }; epicsShareExtern array_at_internal operator<<(std::ostream& str, array_at const& manip); }; class PVAuxInfo; class PostHandler; class PVField; class PVScalar; class PVScalarArray; class PVStructure; class PVUnion; template class PVScalarValue; template class PVValueArray; /** * typedef for a pointer to a PVAuxInfo. */ typedef std::tr1::shared_ptr PVAuxInfoPtr; /** * typedef for a pointer to a PostHandler. */ typedef std::tr1::shared_ptr PostHandlerPtr; /** * typedef for a pointer to a PVField. */ typedef std::tr1::shared_ptr PVFieldPtr; /** * typedef for a pointer to a array of pointer to PVField. */ typedef std::vector PVFieldPtrArray; typedef std::vector::iterator PVFieldPtrArray_iterator; typedef std::vector::const_iterator PVFieldPtrArray_const__iterator; /** * typedef for a pointer to a PVScalar. */ typedef std::tr1::shared_ptr PVScalarPtr; /** * typedef for a pointer to a PVScalarArray. */ typedef std::tr1::shared_ptr PVScalarArrayPtr; /** * typedef for a pointer to a PVStructure. */ typedef std::tr1::shared_ptr PVStructurePtr; /** * typedef for a pointer to a array of pointer to PVStructure. */ typedef std::vector PVStructurePtrArray; typedef std::vector::iterator PVStructurePtrArray_iterator; typedef std::vector::const_iterator PVStructurePtrArray_const__iterator; /** * typedef for a pointer to a PVStructureArray. */ typedef PVValueArray PVStructureArray; typedef std::tr1::shared_ptr PVStructureArrayPtr; typedef std::vector PVStructureArrayPtrArray; typedef std::tr1::shared_ptr PVStructureArrayPtrArrayPtr; /** * typedef for a pointer to a PVUnion. */ typedef std::tr1::shared_ptr PVUnionPtr; /** * typedef for a pointer to a array of pointer to PVUnion. */ typedef std::vector PVUnionPtrArray; typedef std::vector::iterator PVUnionPtrArray_iterator; typedef std::vector::const_iterator PVUnionPtrArray_const__iterator; /** * typedef for a pointer to a PVUnionArray. */ typedef PVValueArray PVUnionArray; typedef std::tr1::shared_ptr PVUnionArrayPtr; typedef std::vector PVUnionArrayPtrArray; typedef std::tr1::shared_ptr PVUnionArrayPtrArrayPtr; class PVDataCreate; typedef std::tr1::shared_ptr PVDataCreatePtr; /** * This class provides auxillary information about a PVField. * Each item is stored as a PVScalar. * A (key,value) is provided for accessing the items where the key is a String. */ class epicsShareClass PVAuxInfo : private NoDefaultMethods { public: typedef std::map PVInfoMap; typedef std::map::iterator PVInfoIter; typedef std::pair PVInfoPair; /** * Constructor * @param The fields to which the Auxinfo is attached. */ PVAuxInfo(PVField *pvField); /** * Destructor */ ~PVAuxInfo(); /** * Get the PVField to which the Auxinfo is attached. * @return The fields to which the Auxinfo is attached. */ PVField * getPVField(); /** * Add a new auxiliary item or retrieve the interface to an existing item. * * @param key The key. * @param scalarType The scalarType for the new item being added/ * @return The new PVScalar that has been added to the Auxinfo. */ PVScalarPtr createInfo(String const & key,ScalarType scalarType); /** * Get the Auxinfo with the specified key. * @return The PVScalar or null if it does not exist. */ PVScalarPtr getInfo(String const & key); /** * Get the map for the info. * @return The map; */ PVInfoMap & getInfoMap(); /** * Convert the Auxinfo to a string and add it to builder. * @param builder The string builder. */ void toString(StringBuilder buf); /** * Convert the Auxinfo to a string and add it to builder. * @param builder The string builder. * @param indentLevel The number of blanks at the beginning of new lines. */ void toString(StringBuilder buf,int indentLevel); private: PVScalarPtr nullPVScalar; PVField * pvField; PVInfoMap pvInfos; friend class PVDataCreate; }; /** * This class is implemented by code that calls setPostHander */ class epicsShareClass PostHandler { public: POINTER_DEFINITIONS(PostHandler); /** * Destructor */ virtual ~PostHandler(){} /** * This is called evertime postPut is called for this field. */ virtual void postPut() = 0; }; /** * PVField is the base class for each PVData field. * Each PVData field has an interface that extends PVField. */ class epicsShareClass PVField : virtual public Serializable, public std::tr1::enable_shared_from_this { public: POINTER_DEFINITIONS(PVField); /** * Constructor */ PVField() {}; /** * Destructor */ virtual ~PVField(); /** * Called to report errors associated with the field. * @param message The message. * @param messageType The message type. */ virtual void message(String message,MessageType messageType) ; /** * Get the fieldName for this field. * @return The name or empty string if top level field. */ 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. * @param prequester The requester. */ virtual void setRequester(RequesterPtr const &prequester); /** * Get offset of the PVField field within top level structure. * Every field within the PVStructure has a unique offset. * The top level structure has an offset of 0. * The first field within the structure has offset equal to 1. * The other offsets are determined by recursively traversing each structure of the tree. * @return The offset. */ std::size_t getFieldOffset() const; /** * Get the next offset. If the field is a scalar or array field then this is just offset + 1. * If the field is a structure it is the offset of the next field after this structure. * Thus (nextOffset - offset) is always equal to the number of fields within the field. * @return The offset. */ std::size_t getNextFieldOffset() const; /** * Get the total number of fields in this field. * This is equal to nextFieldOffset - fieldOffset. */ std::size_t getNumberFields() const; /** * Get the PVAuxInfo interface for the PVField. * @return The PVAuxInfo interface. */ PVAuxInfoPtr & getPVAuxInfo(); /** * Is the field immutable, i.e. does it not allow changes. * @return (false,true) if it (is not, is) immutable. */ bool isImmutable() const; /** * 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. */ virtual void setImmutable(); /** * Get the Field that describes the field. * @return Field, which is the reflection interface. */ const FieldConstPtr & getField() const ; /** * Get the parent of this field. * @return The parent interface or null if this is PVRecord */ PVStructure * getParent() const ; /** * Replace the data implementation for the field. * @param newPVField The new implementation */ void replacePVField(const PVFieldPtr& newPVField); /** * Rename the field name. * @param newName The new name. */ void renameField(String const & newName); /** * postPut. Called when the field is updated by the implementation. */ void postPut() ; /** * Set the handler for postPut. * At most one handler can be set. * @param postHandler The handler. */ void setPostHandler(PostHandlerPtr const &postHandler); /** * Is this field equal to another field. * @param pv other field * @return (false,true) if (is not,is) equal. */ virtual bool equals(PVField &pv); /** * Convert the PVField to a string. * @param buf buffer for the result */ virtual void toString(StringBuilder buf) ; /** * Convert the PVField to a string. * Each line is indented. * @param buf buffer for the result * @param indentLevel The indentation level. */ virtual void toString(StringBuilder buf,int indentLevel) ; /** * Puts the PVField raw value to the stream. * @param o output stream. * @return The output stream. */ virtual std::ostream& dumpValue(std::ostream& o) const = 0; protected: PVField::shared_pointer getPtrSelf() { return shared_from_this(); } PVField(FieldConstPtr field); void setParentAndName(PVStructure *parent, String const & fieldName); void replaceField(FieldConstPtr &field); private: void message(String message,MessageType messageType,String fullFieldName); static void computeOffset(const PVField *pvField); static void computeOffset(const PVField *pvField,std::size_t offset); String notImplemented; PVAuxInfoPtr pvAuxInfo; String fieldName; PVStructure *parent; FieldConstPtr field; size_t fieldOffset; size_t nextFieldOffset; bool immutable; RequesterPtr requester; PostHandlerPtr postHandler; friend class PVDataCreate; friend class PVStructure; }; epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVField& f); /** * PVScalar is the base class for each scalar field. */ class epicsShareClass PVScalar : public PVField { // friend our child class(s) so that it // can call protected methods of other // PVScalar instances. template friend class PVScalarValue; public: POINTER_DEFINITIONS(PVScalar); /** * Destructor */ virtual ~PVScalar(); typedef PVScalar &reference; typedef const PVScalar& const_reference; /** * Get the Scalar introspection interface for the PVScalar. * @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() for value conversion. @code PVScalar* pv = ...; uint32 val = pv->getAs(); @endcode */ template inline T getAs() const { T result; this->getAs((void*)&result, (ScalarType)ScalarTypeID::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() for value conversion. @code PVScalar* pv = ...; pv->putFrom((int32)42); @endcode */ template inline void putFrom(T val) { this->putFrom((const void*)&val, (ScalarType)ScalarTypeID::value); } protected: virtual void putFrom(const void *, ScalarType) = 0; public: virtual void assign(const PVScalar&) = 0; protected: PVScalar(ScalarConstPtr const & scalar); }; /** * Class that holds the data for each posssible scalar type. */ template class epicsShareClass PVScalarValue : public PVScalar { public: POINTER_DEFINITIONS(PVScalarValue); typedef T value_type; typedef T* pointer; typedef const T* const_pointer; static const ScalarType typeCode; /** * Destructor */ virtual ~PVScalarValue() {} /** * Get the value. * @return The value. */ virtual T get() const = 0; /** * Put a new value into the PVScalar. * @param The value. */ virtual void put(T value) = 0; std::ostream& dumpValue(std::ostream& o) const { return o << get(); } // get operator // double value; doubleField >>= value; // NOTE: virtual is needed for MS C++ compiler to get this operator exported virtual void operator>>=(T& value) const { value = get(); } // put operator // double value = 12.8; doubleField <<= value; // NOTE: virtual is needed for MS C++ compiler to get this operator exported virtual void operator<<=(T value) { put(value); } template inline T1 getAs() const { T1 result(castUnsafe(get())); return result; } template inline void putFrom(T1 val) { put(castUnsafe(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; }; /** * typedefs for the various possible scalar types. */ typedef PVScalarValue PVBoolean; typedef PVScalarValue PVByte; typedef PVScalarValue PVShort; typedef PVScalarValue PVInt; typedef PVScalarValue PVLong; typedef PVScalarValue PVUByte; typedef PVScalarValue PVUShort; typedef PVScalarValue PVUInt; typedef PVScalarValue PVULong; typedef PVScalarValue PVFloat; typedef PVScalarValue PVDouble; typedef std::tr1::shared_ptr PVBooleanPtr; typedef std::tr1::shared_ptr PVBytePtr; typedef std::tr1::shared_ptr PVShortPtr; typedef std::tr1::shared_ptr PVIntPtr; typedef std::tr1::shared_ptr PVLongPtr; typedef std::tr1::shared_ptr PVUBytePtr; typedef std::tr1::shared_ptr PVUShortPtr; typedef std::tr1::shared_ptr PVUIntPtr; typedef std::tr1::shared_ptr PVULongPtr; typedef std::tr1::shared_ptr PVFloatPtr; typedef std::tr1::shared_ptr PVDoublePtr; /** * PVString is special case, since it implements SerializableArray */ class epicsShareClass PVString : public PVScalarValue, SerializableArray { public: /** * Destructor */ virtual ~PVString() {} protected: PVString(ScalarConstPtr const & scalar) : PVScalarValue(scalar) {} }; typedef std::tr1::shared_ptr PVStringPtr; /** * PVArray is the base class for all array types, i.e. the scalarArray types and structureArray. */ class epicsShareClass PVArray : public PVField, public SerializableArray { public: POINTER_DEFINITIONS(PVArray); /** * Constructor */ PVArray(){}; /** * Destructor */ 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. */ virtual void setImmutable(); /** * Get the array length. * @return The length. */ virtual std::size_t getLength() const = 0; /** * Set the array length. * @param The length. */ virtual void setLength(std::size_t length) = 0; /** * Get the array capacity. * @return The capacity. */ virtual std::size_t getCapacity() const = 0; /** * Can the capacity be changed. * @return (false,true) if (can not, can) be changed. */ bool isCapacityMutable() const; /** * Set the mutability of the array capacity. * @return false or true */ void setCapacityMutable(bool isMutable); /** * Set the array capacity. * @param The capacity. */ virtual void setCapacity(std::size_t capacity) = 0; virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0; protected: PVArray(FieldConstPtr const & field); private: bool capacityMutable; friend class PVDataCreate; }; epicsShareExtern std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array); /** * Class provided by caller of get */ template class PVArrayData { private: std::vector init; public: POINTER_DEFINITIONS(PVArrayData); typedef T value_type; typedef T* pointer; typedef const T* const_pointer; /** * The data array. */ std::vector & data; /** * The offset. This is the offset into the actual array of the first element in data, */ std::size_t offset; PVArrayData() : data(init) {} }; /** * Base class for a scalarArray. */ class epicsShareClass PVScalarArray : public PVArray { public: POINTER_DEFINITIONS(PVScalarArray); /** * Constructor */ PVScalarArray() {}; /** * Destructor */ virtual ~PVScalarArray(); typedef PVScalarArray &reference; typedef const PVScalarArray& const_reference; /** * Get the introspection interface * @return The interface. */ const ScalarArrayConstPtr getScalarArray() const ; protected: virtual void _getAsVoid(shared_vector&) const = 0; virtual void _putFromVoid(const shared_vector&) = 0; public: /** * 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 void getAs(shared_vector& out) const { shared_vector temp; _getAsVoid(temp); out = shared_vector_convert(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 inline void putFrom(const shared_vector& inp) { shared_vector temp(static_shared_vector_cast(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 temp; pv._getAsVoid(temp); _putFromVoid(temp); } protected: PVScalarArray(ScalarArrayConstPtr const & scalarArray); private: friend class PVDataCreate; }; class epicsShareClass PVStructure : public PVField, public BitSetSerializable { public: POINTER_DEFINITIONS(PVStructure); /** * Destructor */ virtual ~PVStructure(); typedef PVStructure & reference; typedef const PVStructure & const_reference; /** * 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. */ virtual void setImmutable(); /** * Get the introspection interface * @return The interface. */ StructureConstPtr getStructure() const; /** * Get the array of pointers to the subfields in the structure. * @return The array. */ const PVFieldPtrArray & getPVFields() const; /** * Get the subfield with the specified name. * @param fieldName The name of the field. * @return Pointer to the field or null if field does not exist. */ PVFieldPtr getSubField(String const &fieldName) const; template std::tr1::shared_ptr getSubField(String const &fieldName) const { PVFieldPtr pvField = getSubField(fieldName); if (pvField.get()) return std::tr1::dynamic_pointer_cast(pvField); else return std::tr1::shared_ptr(); } /** * Get the subfield with the specified offset. * @param fieldOffset The offset. * @return Pointer to the field or null if field does not exist. */ PVFieldPtr getSubField(std::size_t fieldOffset) const; template std::tr1::shared_ptr getSubField(std::size_t fieldOffset) const { PVFieldPtr pvField = getSubField(fieldOffset); if (pvField.get()) return std::tr1::dynamic_pointer_cast(pvField); else return std::tr1::shared_ptr(); } /** * Append a field to the structure. * @param fieldName The name of the field to append. * @param pvField The field to append. */ void appendPVField(String const &fieldName,PVFieldPtr const & pvField); /** * Append fields to the structure. * @param fieldNames The names of the fields to add. * @param pvFields The fields to append. * @return Pointer to the field or null if field does not exist. */ void appendPVFields(StringArray const & fieldNames,PVFieldPtrArray const & pvFields); /** * Remove a field from the structure. * @param fieldName The name of the field to remove. */ void removePVField(String const &fieldName); /** * Get a boolean field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVBooleanPtr getBooleanField(String const &fieldName) ; /** * Get a byte field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVBytePtr getByteField(String const &fieldName) ; /** * Get a short field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVShortPtr getShortField(String const &fieldName) ; /** * Get a int field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVIntPtr getIntField(String const &fieldName) ; /** * Get a long field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVLongPtr getLongField(String const &fieldName) ; /** * Get an unsigned byte field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVUBytePtr getUByteField(String const &fieldName) ; /** * Get an unsigned short field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVUShortPtr getUShortField(String const &fieldName) ; /** * Get an unsigned int field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVUIntPtr getUIntField(String const &fieldName) ; /** * Get an unsigned long field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVULongPtr getULongField(String const &fieldName) ; /** * Get a float field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVFloatPtr getFloatField(String const &fieldName) ; /** * Get a double field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVDoublePtr getDoubleField(String const &fieldName) ; /** * Get a string field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVStringPtr getStringField(String const &fieldName) ; /** * Get a structure field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVStructurePtr getStructureField(String const &fieldName) ; /** * Get a union field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVUnionPtr getUnionField(String const &fieldName) ; /** * Get a scalarArray field with the specified name. * @param fieldName The name of the field to get. * @param elementType The element type. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVScalarArrayPtr getScalarArrayField( String const &fieldName,ScalarType elementType) ; /** * Get a structureArray field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVStructureArrayPtr getStructureArrayField(String const &fieldName) ; /** * Get a unionArray field with the specified name. * @param fieldName The name of the field to get. * @return Pointer to the field of null if a field with that name and type does not exist. */ PVUnionArrayPtr getUnionArrayField(String const &fieldName) ; /** * Get the name if this structure extends another structure. * @return The string which may be null. */ String getExtendsStructureName() const; /** * Put the extends name. * @param extendsStructureName The name. */ bool putExtendsStructureName( String const &extendsStructureName); /** * Serialize. * @param pbuffer The byte buffer. * @param pflusher Interface to call when buffer is full. */ virtual void serialize( ByteBuffer *pbuffer,SerializableControl *pflusher) const ; /** * Deserialize * @param pbuffer The byte buffer. * @param pflusher Interface to call when buffer is empty. */ virtual void deserialize( ByteBuffer *pbuffer,DeserializableControl *pflusher); /** * Serialize. * @param pbuffer The byte buffer. * @param pflusher Interface to call when buffer is full. * @param pbitSet A bitset the specifies which fields to serialize. */ virtual void serialize(ByteBuffer *pbuffer, SerializableControl *pflusher,BitSet *pbitSet) const; /** * Deserialize * @param pbuffer The byte buffer. * @param pflusher Interface to call when buffer is empty. * @param pbitSet A bitset the specifies which fields to deserialize. */ virtual void deserialize(ByteBuffer *pbuffer, DeserializableControl*pflusher,BitSet *pbitSet); /** * Constructor * @param structure The introspection interface. */ PVStructure(StructureConstPtr const & structure); /** * Constructor * @param structure The introspection interface. * @param pvFields The array of fields for the structure. */ PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields); virtual std::ostream& dumpValue(std::ostream& o) const; private: void fixParentStructure(); static PVFieldPtr nullPVField; static PVBooleanPtr nullPVBoolean; static PVBytePtr nullPVByte; static PVShortPtr nullPVShort; static PVIntPtr nullPVInt; static PVLongPtr nullPVLong; static PVUBytePtr nullPVUByte; static PVUShortPtr nullPVUShort; static PVUIntPtr nullPVUInt; static PVULongPtr nullPVULong; static PVFloatPtr nullPVFloat; static PVDoublePtr nullPVDouble; static PVStringPtr nullPVString; static PVStructurePtr nullPVStructure; static PVStructureArrayPtr nullPVStructureArray; static PVUnionPtr nullPVUnion; static PVUnionArrayPtr nullPVUnionArray; static PVScalarArrayPtr nullPVScalarArray; PVFieldPtrArray pvFields; StructureConstPtr structurePtr; String extendsStructureName; friend class PVDataCreate; }; class epicsShareClass PVUnion : public PVField { public: POINTER_DEFINITIONS(PVUnion); /** * Destructor */ virtual ~PVUnion(); typedef PVUnion & reference; typedef const PVUnion & const_reference; /** * Undefined index. * Default value upon PVUnion construction. Can be set by the user. * Corresponds to {@code null} value. */ static int32 UNDEFINED_INDEX; /** * Get the introspection interface * @return The interface. */ UnionConstPtr getUnion() const; /** * Get the {@code PVField} value stored in the field. * @return {@code PVField} value of field, {@code null} if {@code getSelectedIndex() == UNDEFINED_INDEX}. */ PVFieldPtr get() const; template std::tr1::shared_ptr get() const { return std::tr1::dynamic_pointer_cast(get()); } /** * Select field (set index) and get the field at the index. * @param index index of the field to select. * @return corresponding PVField (of undetermined value), {@code null} if {@code index == UNDEFINED_INDEX}. * @throws {@code std::invalid_argument} if index is invalid (out of range). */ PVFieldPtr select(int32 index); template std::tr1::shared_ptr select(int32 index) { return std::tr1::dynamic_pointer_cast(select(index)); } /** * Select field (set index) and get the field by given name. * @param fieldName the name of the field to select. * @return corresponding PVField (of undetermined value). * @throws {@code std::invalid_argument} if field does not exist. */ PVFieldPtr select(String const & fieldName); template std::tr1::shared_ptr select(String const & fieldName) { return std::tr1::dynamic_pointer_cast(select(fieldName)); } /** * Get selected field index. * @return selected field index. */ int32 getSelectedIndex() const; /** * Get selected field name. * @return selected field name, empty string if field does not exist. */ String getSelectedFieldName() const; /** * Set the {@code PVField} (by reference!) as selected field. * If a value is not a valid union field an {@code std::invalid_argument} exception is thrown. * @param value the field to set. */ void set(PVFieldPtr const & value); /** * Set the {@code PVField} (by reference!) as field at given index. * If a value is not a valid union field an {@code std::invalid_argument} exception is thrown. * Use {@code select(int)} to put by value. * @param index index of a field to put. * @param value the field to set. * @see #select(int) */ void set(int32 index, PVFieldPtr const & value); /** * Set the {@code PVField} (by reference!) as field by given name. * If a value is not a valid union field an {@code std::invalid_argument} exception is thrown. * Use {@code select(String)} to put by value. * @param fieldName Name of the field to put. * @param value the field to set. * @see #select(String) */ void set(String const & fieldName, PVFieldPtr const & value); /** * Serialize. * @param pbuffer The byte buffer. * @param pflusher Interface to call when buffer is full. */ virtual void serialize( ByteBuffer *pbuffer,SerializableControl *pflusher) const ; /** * Deserialize * @param pbuffer The byte buffer. * @param pflusher Interface to call when buffer is empty. */ virtual void deserialize( ByteBuffer *pbuffer,DeserializableControl *pflusher); /** * Constructor * @param punion The introspection interface. */ PVUnion(UnionConstPtr const & punion); virtual std::ostream& dumpValue(std::ostream& o) const; private: friend class PVDataCreate; UnionConstPtr unionPtr; int32 selector; PVFieldPtr value; bool variant; }; namespace detail { // adaptor to allow epics::pvData::shared_vector to hold a reference // to a shared_ptr > template struct shared_ptr_vector_deletor { typedef std::tr1::shared_ptr > shared_vector; shared_vector vec; shared_ptr_vector_deletor(const shared_vector& v) :vec(v) {} void operator()(T*){vec.reset();} }; template 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 svector; typedef ::epics::pvData::shared_vector const_svector; // begin deprecated typedef PVArrayData ArrayDataType; typedef std::vector vector; typedef const std::vector const_vector; typedef std::tr1::shared_ptr shared_vector; // end deprecated protected: PVVectorStorage() : Base() {} template 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 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(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 class epicsShareClass PVValueArray : public detail::PVVectorStorage { typedef detail::PVVectorStorage 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 svector; typedef ::epics::pvData::shared_vector const_svector; // begin deprecated typedef PVArrayData ArrayDataType; typedef std::vector vector; typedef const std::vector const_vector; typedef std::tr1::shared_ptr shared_vector; typedef PVValueArray & reference; typedef const PVValueArray & const_reference; // end deprecated static const ScalarType typeCode; /** * Destructor */ virtual ~PVValueArray() {} std::ostream& dumpValue(std::ostream& o) const { const_svector v(this->view()); typename const_svector::const_iterator it(v.begin()), end(v.end()); o << '['; 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 << print_cast(this->view().at(index)); } protected: virtual void _getAsVoid(epics::pvData::shared_vector& out) const { out = static_shared_vector_cast(this->view()); } virtual void _putFromVoid(const epics::pvData::shared_vector& in) { // TODO: try to re-use storage this->replace(shared_vector_convert(in)); } PVValueArray(ScalarArrayConstPtr const & scalar) : base_t(scalar) {} friend class PVDataCreate; }; /** * This is provided by code that calls get. */ typedef PVArrayData StructureArrayData; /** * Data class for a structureArray */ template<> class epicsShareClass PVValueArray : public detail::PVVectorStorage { typedef detail::PVVectorStorage base_t; public: POINTER_DEFINITIONS(PVStructureArray); typedef PVStructurePtr value_type; typedef PVStructurePtr* pointer; typedef const PVStructurePtr* const_pointer; typedef PVArrayData ArrayDataType; typedef std::vector vector; typedef const std::vector const_vector; typedef std::tr1::shared_ptr 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 svector; typedef ::epics::pvData::shared_vector 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; }; /** * This is provided by code that calls get. */ typedef PVArrayData UnionArrayData; /** * Data class for a unionArray */ template<> class epicsShareClass PVValueArray : public detail::PVVectorStorage { typedef detail::PVVectorStorage base_t; public: POINTER_DEFINITIONS(PVUnionArray); typedef PVUnionPtr value_type; typedef PVUnionPtr* pointer; typedef const PVUnionPtr* const_pointer; typedef PVArrayData ArrayDataType; typedef std::vector vector; typedef const std::vector const_vector; typedef std::tr1::shared_ptr shared_vector; typedef PVUnionArray &reference; typedef const PVUnionArray& const_reference; //TODO: full namespace can be removed along with local typedef 'shared_vector' typedef ::epics::pvData::shared_vector svector; typedef ::epics::pvData::shared_vector 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. */ UnionArrayConstPtr getUnionArray() const {return unionArray;} /** * 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(UnionArrayConstPtr const & unionArray) :base_t(unionArray) ,unionArray(unionArray) {} private: UnionArrayConstPtr unionArray; const_svector value; friend class PVDataCreate; }; /** * Definitions for the various scalarArray types. */ typedef PVArrayData BooleanArrayData; typedef PVValueArray PVBooleanArray; typedef std::tr1::shared_ptr PVBooleanArrayPtr; typedef PVArrayData ByteArrayData; typedef PVValueArray PVByteArray; typedef std::tr1::shared_ptr PVByteArrayPtr; typedef PVArrayData ShortArrayData; typedef PVValueArray PVShortArray; typedef std::tr1::shared_ptr PVShortArrayPtr; typedef PVArrayData IntArrayData; typedef PVValueArray PVIntArray; typedef std::tr1::shared_ptr PVIntArrayPtr; typedef PVArrayData LongArrayData; typedef PVValueArray PVLongArray; typedef std::tr1::shared_ptr PVLongArrayPtr; typedef PVArrayData UByteArrayData; typedef PVValueArray PVUByteArray; typedef std::tr1::shared_ptr PVUByteArrayPtr; typedef PVArrayData UShortArrayData; typedef PVValueArray PVUShortArray; typedef std::tr1::shared_ptr PVUShortArrayPtr; typedef PVArrayData UIntArrayData; typedef PVValueArray PVUIntArray; typedef std::tr1::shared_ptr PVUIntArrayPtr; typedef PVArrayData ULongArrayData; typedef PVValueArray PVULongArray; typedef std::tr1::shared_ptr PVULongArrayPtr; typedef PVArrayData FloatArrayData; typedef PVValueArray PVFloatArray; typedef std::tr1::shared_ptr PVFloatArrayPtr; typedef PVArrayData DoubleArrayData; typedef PVValueArray PVDoubleArray; typedef std::tr1::shared_ptr PVDoubleArrayPtr; typedef PVArrayData StringArrayData; typedef PVValueArray PVStringArray; typedef std::tr1::shared_ptr PVStringArrayPtr; /** * This is a singlton class for creating data instances. */ class epicsShareClass PVDataCreate { public: static PVDataCreatePtr getPVDataCreate(); /** * Create a PVField using given Field introspection data. * @param field The introspection data to be used to create PVField. * @return The PVField implementation. */ PVFieldPtr createPVField(FieldConstPtr const & field); /** * Create a PVField using given a PVField to clone. * This method calls the appropriate createPVScalar, createPVArray, or createPVStructure. * @param fieldToClone The field to clone. * @return The PVField implementation */ PVFieldPtr createPVField(PVFieldPtr const & fieldToClone); /** * Create an implementation of a scalar field reusing the Scalar introspection interface. * @param scalar The introspection interface. * @return The PVScalar implementation. */ PVScalarPtr createPVScalar(ScalarConstPtr const & scalar); /** * Create an implementation of a scalar field. A Scalar introspection interface is created. * @param fieldType The field type. * @return The PVScalar implementation. */ PVScalarPtr createPVScalar(ScalarType scalarType); /** * Create an implementation of a scalar field by cloning an existing PVScalar. * The new PVScalar will have the same value and auxInfo as the original. * @param scalarToClone The PVScalar to clone. * @return The PVScalar implementation. */ PVScalarPtr createPVScalar(PVScalarPtr const & scalarToClone); /** * Create an implementation of an array field reusing the Array introspection interface. * @param array The introspection interface. * @return The PVScalarArray implementation. */ PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray); /** * Create an implementation for an array field. An Array introspection interface is created. * @param parent The parent interface. * @param elementType The element type. * @return The PVScalarArray implementation. */ PVScalarArrayPtr createPVScalarArray(ScalarType elementType); /** * Create an implementation of an array field by cloning an existing PVArray. * The new PVArray will have the same value and auxInfo as the original. * @param arrayToClone The PVScalarArray to clone. * @return The PVScalarArray implementation. */ PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const & scalarArrayToClone); /** * Create an implementation of an array with structure elements. * @param structureArray The introspection interface. * All elements share the same introspection interface. * @return The PVStructureArray implementation. */ PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const & structureArray); /** * Create implementation for PVStructure. * @param structure The introspection interface. * @return The PVStructure implementation */ PVStructurePtr createPVStructure(StructureConstPtr const & structure); /** * Create implementation for PVStructure. * @param fieldNames The field names. * @param pvFields Array of PVFields * @return The PVStructure implementation */ PVStructurePtr createPVStructure( StringArray const & fieldNames,PVFieldPtrArray const & pvFields); /** * Create implementation for PVStructure. * @param structToClone A structure. Each subfield and any auxInfo is cloned and added to the newly created structure. * @return The PVStructure implementation. */ PVStructurePtr createPVStructure(PVStructurePtr const & structToClone); /** * Create an implementation of an array with union elements. * @param unionArray The introspection interface. * All elements share the same introspection interface. * @return The PVUnionArray implementation. */ PVUnionArrayPtr createPVUnionArray(UnionArrayConstPtr const & unionArray); /** * Create implementation for PVUnion. * @param union The introspection interface. * @return The PVUnion implementation */ PVUnionPtr createPVUnion(UnionConstPtr const & punion); /** * Create implementation for PVUnion. * @param unionToClone A union. Each subfield is cloned and added to the newly created union. * @return The PVUnion implementation. */ PVUnionPtr createPVUnion(PVUnionPtr const & unionToClone); /** * Create variant union implementation. * @return The variant PVUnion implementation. */ PVUnionPtr createPVVariantUnion(); /** * Create variant union array implementation. * @return The variant PVUnionArray implementation. */ PVUnionArrayPtr createPVVariantUnionArray(); template std::tr1::shared_ptr createPVScalar() { return std::tr1::static_pointer_cast(createPVScalar(PVT::typeCode)); } template std::tr1::shared_ptr createPVScalarArray() { return std::tr1::static_pointer_cast(createPVScalarArray(PVAT::typeCode)); } PVStructureArrayPtr createPVStructureArray(StructureConstPtr const & structure) { return createPVStructureArray(fieldCreate->createStructureArray(structure)); } PVUnionArrayPtr createPVUnionArray(UnionConstPtr const & punion) { return createPVUnionArray(fieldCreate->createUnionArray(punion)); } private: PVDataCreate(); FieldCreatePtr fieldCreate; }; /** * Get the single class that implemnents PVDataCreate * @param The PVDataCreate factory. */ epicsShareExtern PVDataCreatePtr getPVDataCreate(); #undef USAGE_DEPRECATED #undef USAGE_ERROR }} #endif /* PVDATA_H */