Program Listing for File pvData.h

Return to documentation for file (src/pv/pvData.h)

/* pvData.h */
/*
 * Copyright information and license terms for this software can be
 * found in the file LICENSE that is included with the distribution
 */
#ifndef PVDATA_H
#define PVDATA_H

#include <string>
#include <map>
#include <stdexcept>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <iomanip>

#include <epicsAssert.h>

#include <pv/pvIntrospect.h>
#include <pv/typeCast.h>
#include <pv/anyscalar.h>
#include <pv/sharedVector.h>

#include <shareLib.h>
#include <compilerDependencies.h>

#if defined(vxWorks) && !defined(_WRS_VXWORKS_MAJOR)
typedef class std::ios std::ios_base;
#endif

namespace epics { namespace pvData {

class PostHandler;

class PVField;
class PVScalar;

class PVScalarArray;

class PVStructure;

class PVUnion;



template<typename T> class PVScalarValue;
template<typename T> class PVValueArray;


typedef std::tr1::shared_ptr<PostHandler> PostHandlerPtr;

typedef std::tr1::shared_ptr<PVField> PVFieldPtr;
typedef std::vector<PVFieldPtr> PVFieldPtrArray;
typedef std::vector<PVFieldPtr>::iterator PVFieldPtrArray_iterator;
typedef std::vector<PVFieldPtr>::const_iterator PVFieldPtrArray_const__iterator;

typedef std::tr1::shared_ptr<PVScalar> PVScalarPtr;

typedef std::tr1::shared_ptr<PVScalarArray> PVScalarArrayPtr;

typedef std::tr1::shared_ptr<PVStructure> PVStructurePtr;
typedef std::vector<PVStructurePtr> PVStructurePtrArray;
typedef std::vector<PVStructurePtr>::iterator PVStructurePtrArray_iterator;
typedef std::vector<PVStructurePtr>::const_iterator PVStructurePtrArray_const__iterator;

typedef PVValueArray<PVStructurePtr> PVStructureArray;
typedef std::tr1::shared_ptr<PVStructureArray> PVStructureArrayPtr;
typedef std::vector<PVStructureArrayPtr> PVStructureArrayPtrArray;
typedef std::tr1::shared_ptr<PVStructureArrayPtrArray> PVStructureArrayPtrArrayPtr;

typedef std::tr1::shared_ptr<PVUnion> PVUnionPtr;
typedef std::vector<PVUnionPtr> PVUnionPtrArray;
typedef std::vector<PVUnionPtr>::iterator PVUnionPtrArray_iterator;
typedef std::vector<PVUnionPtr>::const_iterator PVUnionPtrArray_const__iterator;

typedef PVValueArray<PVUnionPtr> PVUnionArray;
typedef std::tr1::shared_ptr<PVUnionArray> PVUnionArrayPtr;
typedef std::vector<PVUnionArrayPtr> PVUnionArrayPtrArray;
typedef std::tr1::shared_ptr<PVUnionArrayPtrArray> PVUnionArrayPtrArrayPtr;

class PVDataCreate;
typedef std::tr1::shared_ptr<PVDataCreate> PVDataCreatePtr;

class epicsShareClass PostHandler
{
public:
    POINTER_DEFINITIONS(PostHandler);
    virtual ~PostHandler(){}
    virtual void postPut() = 0;
};

class epicsShareClass PVField
: virtual public Serializable,
  public std::tr1::enable_shared_from_this<PVField>
{
public:
    POINTER_DEFINITIONS(PVField);
    virtual ~PVField();
    inline const std::string& getFieldName() const {return fieldName;}
    std::string getFullName() const;
    std::size_t getFieldOffset() const;
    std::size_t getNextFieldOffset() const;
    std::size_t getNumberFields() const;
    inline bool isImmutable() const {return immutable;}
    virtual void setImmutable();
    inline const FieldConstPtr & getField() const {return field;}
    inline PVStructure * getParent() {return parent;}
    inline const PVStructure * getParent() const {return parent;}
    void postPut() ;
    void setPostHandler(PostHandlerPtr const &postHandler);
    virtual bool equals(PVField &pv);
    virtual std::ostream& dumpValue(std::ostream& o) const = 0;

    void copy(const PVField& from);
    void copyUnchecked(const PVField& from);

    static size_t num_instances; // use atomic::get() or volatile* access
    enum {isPVField=1};
protected:
    PVField::shared_pointer getPtrSelf()
    {
        return shared_from_this();
    }
    explicit PVField(FieldConstPtr field);
    void setParentAndName(PVStructure *parent, std::string const & fieldName);
private:
    static void computeOffset(const PVField *pvField);
    static void computeOffset(const PVField *pvField,std::size_t offset);
    std::string fieldName;
    PVStructure *parent;
    const FieldConstPtr field;
    size_t fieldOffset;
    size_t nextFieldOffset;
    bool immutable;
    PostHandlerPtr postHandler;
    friend class PVDataCreate;
    friend class PVStructure;
    EPICS_NOT_COPYABLE(PVField)
};

epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVField& f);

class epicsShareClass 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);
    virtual ~PVScalar();
    typedef PVScalar &reference;
    typedef const PVScalar& const_reference;
    const ScalarConstPtr getScalar() const ;

    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:

    virtual void getAs(AnyScalar& v) const =0;

    template<typename T>
    inline void putFrom(T val) {
        this->putFrom((const void*)&val, (ScalarType)ScalarTypeID<T>::value);
    }

    virtual void putFrom(const void *, ScalarType) = 0;

    inline void putFrom(const AnyScalar& v) {
        if(v)
            putFrom(v.unsafe(), v.type());
    }

    virtual void assign(const PVScalar&) = 0;

    virtual void copy(const PVScalar& from) = 0;
    virtual void copyUnchecked(const PVScalar& from) = 0;

protected:
    explicit PVScalar(ScalarConstPtr const & scalar);
    EPICS_NOT_COPYABLE(PVScalar)
};

namespace detail {
template<typename T>
struct ScalarStorageOps {
    T value;
    typedef T arg_type;
    inline void store(T v) {
        value = v;
    }
    ScalarStorageOps() :value(0) {}
};
template<>
struct ScalarStorageOps<std::string> {
    std::string value;
    size_t maxLength;
    typedef const std::string& arg_type;
    void store(const std::string& val) {
        if (maxLength > 0 && val.length() > maxLength)
            throw std::overflow_error("string too long");

        value = val;
    }

    ScalarStorageOps(): value(), maxLength(0) {} // initialized in PVString::PVString
};
} // namespace detail

template<typename T>
class epicsShareClass PVScalarValue : public PVScalar {
    typedef detail::ScalarStorageOps<T> storage_t;
public:
    POINTER_DEFINITIONS(PVScalarValue);
    typedef T value_type;
    typedef T* pointer;
    typedef const T* const_pointer;

    static const ScalarType typeCode;

    virtual ~PVScalarValue();
    typename storage_t::arg_type get() const { return storage.value; }
    inline void put(typename storage_t::arg_type v) {
        storage.store(v);
        PVField::postPut();
    }

    virtual std::ostream& dumpValue(std::ostream& o) const OVERRIDE;

    // 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;

    // put operator
    // double value = 12.8; doubleField <<= value;
    // NOTE: virtual is needed for MS C++ compiler to get this operator exported
    virtual void operator<<=(typename storage_t::arg_type value);

    template<typename T1>
    inline T1 getAs() const {
        T1 result(castUnsafe<T1,T>(get()));
        return result;
    }

    template<typename T1>
    inline void putFrom(typename detail::ScalarStorageOps<T1>::arg_type val) {
        put(castUnsafe<T,T1>(val));
    }

    inline void putFrom(const AnyScalar& v) {
        // the template form of putFrom() hides the base class AnyScalar overload
        PVScalar::putFrom(v);
    }

    virtual void assign(const PVScalar& scalar) OVERRIDE FINAL;
    virtual void copy(const PVScalar& from) OVERRIDE FINAL;
    virtual void copyUnchecked(const PVScalar& from) OVERRIDE FINAL;

    virtual void serialize(ByteBuffer *pbuffer,
        SerializableControl *pflusher) const OVERRIDE;
    virtual void deserialize(ByteBuffer *pbuffer,
        DeserializableControl *pflusher) OVERRIDE FINAL;

protected:
    explicit PVScalarValue(ScalarConstPtr const & scalar)
    : PVScalar(scalar), storage() {}
    virtual void getAs(void * result, ScalarType rtype) const OVERRIDE FINAL
    {
        const T src = get();
        castUnsafeV(1, rtype, result, typeCode, (const void*)&src);
    }
public:
    virtual void getAs(AnyScalar& v) const OVERRIDE FINAL
    {
        v = get();
    }
    virtual void putFrom(const void *src, ScalarType stype) OVERRIDE FINAL
    {
        T result;
        castUnsafeV(1, typeCode, (void*)&result, stype, src);
        put(result);
    }
protected:

    friend class PVDataCreate;
    storage_t storage;
    EPICS_NOT_COPYABLE(PVScalarValue)
};

template<> inline
std::ostream& PVScalarValue<int8>::dumpValue(std::ostream& o) const
{
    return o << static_cast<int>(get());
}

template<> inline
std::ostream& PVScalarValue<uint8>::dumpValue(std::ostream& o) const
{
    return o << static_cast<unsigned int>(get());
}

template<> inline
std::ostream& PVScalarValue<boolean>::dumpValue(std::ostream& o) const
{
    return o << std::boolalpha << static_cast<bool>(get());
}

/*
 * typedefs for the various possible scalar types.
 */
typedef PVScalarValue<boolean> PVBoolean;
typedef PVScalarValue<int8> PVByte;
typedef PVScalarValue<int16> PVShort;
typedef PVScalarValue<int32> PVInt;
typedef PVScalarValue<int64> PVLong;
typedef PVScalarValue<uint8> PVUByte;
typedef PVScalarValue<uint16> PVUShort;
typedef PVScalarValue<uint32> PVUInt;
typedef PVScalarValue<uint64> PVULong;
typedef PVScalarValue<float> PVFloat;
typedef PVScalarValue<double> PVDouble;
typedef std::tr1::shared_ptr<PVBoolean> PVBooleanPtr;
typedef std::tr1::shared_ptr<PVByte> PVBytePtr;
typedef std::tr1::shared_ptr<PVShort> PVShortPtr;
typedef std::tr1::shared_ptr<PVInt> PVIntPtr;
typedef std::tr1::shared_ptr<PVLong> PVLongPtr;
typedef std::tr1::shared_ptr<PVUByte> PVUBytePtr;
typedef std::tr1::shared_ptr<PVUShort> PVUShortPtr;
typedef std::tr1::shared_ptr<PVUInt> PVUIntPtr;
typedef std::tr1::shared_ptr<PVULong> PVULongPtr;
typedef std::tr1::shared_ptr<PVFloat> PVFloatPtr;
typedef std::tr1::shared_ptr<PVDouble> PVDoublePtr;

class epicsShareClass PVString : public PVScalarValue<std::string>, SerializableArray {
public:
    virtual ~PVString() {}

    virtual std::ostream& dumpValue(std::ostream& o) const OVERRIDE FINAL;

    virtual void serialize(ByteBuffer *pbuffer,
        SerializableControl *pflusher) const OVERRIDE FINAL;
    virtual void serialize(ByteBuffer *pbuffer,
        SerializableControl *pflusher, size_t offset, size_t count) const OVERRIDE FINAL;
protected:
    explicit PVString(ScalarConstPtr const & scalar);

    friend class PVDataCreate;
    EPICS_NOT_COPYABLE(PVString)
};
typedef std::tr1::shared_ptr<PVString> PVStringPtr;


class epicsShareClass PVArray : public PVField, public SerializableArray {
public:
    POINTER_DEFINITIONS(PVArray);
    virtual ~PVArray(){};
    virtual ArrayConstPtr getArray() const = 0;
    virtual void setImmutable() OVERRIDE;
    virtual std::size_t getLength() const = 0;
    virtual void setLength(std::size_t length) = 0;
    virtual std::size_t getCapacity() const = 0;
    bool isCapacityMutable() const;
    void setCapacityMutable(bool isMutable);
    virtual void setCapacity(std::size_t capacity) = 0;

    using PVField::dumpValue;
    virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const = 0;

protected:
    explicit PVArray(FieldConstPtr const & field);
    void checkLength(size_t length) const;
private:
    bool capacityMutable;
    friend class PVDataCreate;
    EPICS_NOT_COPYABLE(PVArray)
};

epicsShareExtern std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array);

class epicsShareClass PVScalarArray : public PVArray {
public:
    POINTER_DEFINITIONS(PVScalarArray);
    virtual ~PVScalarArray();
    typedef PVScalarArray &reference;
    typedef const PVScalarArray& const_reference;
    const ScalarArrayConstPtr getScalarArray() const ;

protected:
    virtual void _getAsVoid(shared_vector<const void>&) const = 0;
    virtual void _putFromVoid(const shared_vector<const void>&) = 0;
public:

    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);
    }

    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);
    }

    void assign(const PVScalarArray& pv) {
        if (isImmutable())
            throw std::invalid_argument("destination is immutable");
        copyUnchecked(pv);
    }

    void copy(const PVScalarArray& from) {
        assign(from);
    }

    void copyUnchecked(const PVScalarArray& from) {
        if (this==&from)
            return;
        shared_vector<const void> temp;
        from._getAsVoid(temp);
        _putFromVoid(temp);
    }

protected:
    explicit PVScalarArray(ScalarArrayConstPtr const & scalarArray);
private:
    friend class PVDataCreate;
    EPICS_NOT_COPYABLE(PVScalarArray)
};


class epicsShareClass PVStructure : public PVField, public BitSetSerializable
{
public:
    POINTER_DEFINITIONS(PVStructure);
    virtual ~PVStructure();
    typedef PVStructure & reference;
    typedef const PVStructure & const_reference;
    virtual void setImmutable() OVERRIDE FINAL;
    inline const StructureConstPtr &getStructure() const { return structurePtr; }
    inline const PVFieldPtrArray & getPVFields() const { return pvFields; }

    template<typename A>
    FORCE_INLINE std::tr1::shared_ptr<PVField> getSubField(A a)
    {
        return getSubFieldImpl(a, false);
    }

    template<typename A>
    FORCE_INLINE std::tr1::shared_ptr<const PVField> getSubField(A a) const
    {
        return getSubFieldImpl(a, false);
    }

    template<typename PVD, typename A>
    inline std::tr1::shared_ptr<PVD> getSubField(A a)
    {
        STATIC_ASSERT(PVD::isPVField); // only allow cast from PVField sub-class
        return std::tr1::dynamic_pointer_cast<PVD>(getSubFieldImpl(a, false));
    }

    template<typename PVD, typename A>
    inline std::tr1::shared_ptr<const PVD> getSubField(A a) const
    {
        STATIC_ASSERT(PVD::isPVField); // only allow cast from PVField sub-class
        return std::tr1::dynamic_pointer_cast<const PVD>(getSubFieldImpl(a, false));
    }

    template<typename A>
    FORCE_INLINE std::tr1::shared_ptr<PVField> getSubFieldT(A a)
    {
        return getSubFieldImpl(a, true);
    }

    template<typename A>
    FORCE_INLINE std::tr1::shared_ptr<const PVField> getSubFieldT(A a) const
    {
        return getSubFieldImpl(a, true);
    }

private:
    static void throwBadFieldType(const char *name);
    static void throwBadFieldType(std::size_t fieldOffset);
    static FORCE_INLINE void throwBadFieldType(const std::string& name) {
        throwBadFieldType(name.c_str());
    }
public:

    template<typename PVD, typename A>
    inline std::tr1::shared_ptr<PVD> getSubFieldT(A a)
    {
        STATIC_ASSERT(PVD::isPVField); // only allow cast from PVField sub-class
        std::tr1::shared_ptr<PVD> ret(std::tr1::dynamic_pointer_cast<PVD>(getSubFieldImpl(a, true)));
        if(!ret)
            throwBadFieldType(a);
        return ret;
    }

    template<typename PVD, typename A>
    inline std::tr1::shared_ptr<const PVD> getSubFieldT(A a) const
    {
        STATIC_ASSERT(PVD::isPVField); // only allow cast from PVField sub-class
        std::tr1::shared_ptr<const PVD> ret(std::tr1::dynamic_pointer_cast<const PVD>(getSubFieldImpl(a, true)));
        if(!ret)
            throwBadFieldType(a);
        return ret;
    }

    virtual void serialize(
        ByteBuffer *pbuffer,SerializableControl *pflusher) const OVERRIDE FINAL;
    virtual void deserialize(
        ByteBuffer *pbuffer,DeserializableControl *pflusher) OVERRIDE FINAL;
    virtual void serialize(ByteBuffer *pbuffer,
        SerializableControl *pflusher,BitSet *pbitSet) const OVERRIDE FINAL;
    virtual void deserialize(ByteBuffer *pbuffer,
        DeserializableControl*pflusher,BitSet *pbitSet) OVERRIDE FINAL;
    explicit PVStructure(StructureConstPtr const & structure);
    PVStructure(StructureConstPtr const & structure,PVFieldPtrArray const & pvFields);

    virtual std::ostream& dumpValue(std::ostream& o) const OVERRIDE FINAL;

    void copy(const PVStructure& from);

    void copyUnchecked(const PVStructure& from);
    void copyUnchecked(const PVStructure& from, const BitSet& maskBitSet, bool inverse = false);

    struct Formatter {
        enum mode_t {
            Auto,
            Plain,
            ANSI,
        };
        enum format_t {
            Raw,
            NT,
            JSON,
        };
    private:
        const PVStructure& xtop;
        const BitSet* xshow;
        const BitSet* xhighlight;
        mode_t xmode;
        format_t xfmt;
    public:
        explicit Formatter(const PVStructure& top)
            :xtop(top)
            ,xshow(0)
            ,xhighlight(0)
            ,xmode(Auto)
            ,xfmt(NT)
        {}

        // those fields (and their parents) to be printed.  non-NT mode.
        FORCE_INLINE Formatter& show(const BitSet& set) { xshow = &set; return *this; }
        // those fields (and not their parents) to be specially highlighted.  non-NT mode.
        FORCE_INLINE Formatter& highlight(const BitSet& set) { xhighlight = &set; return *this; }

        FORCE_INLINE Formatter& mode(mode_t m) { xmode = m; return *this; }

        FORCE_INLINE Formatter& format(format_t f) { xfmt = f; return *this; }

        friend epicsShareFunc std::ostream& operator<<(std::ostream& strm, const Formatter& format);
        friend void printRaw(std::ostream& strm, const PVStructure::Formatter& format, const PVStructure& cur);
    };

    FORCE_INLINE Formatter stream() const { return Formatter(*this); }

private:

    inline PVFieldPtr getSubFieldImpl(const std::string& name, bool throws) const {
        return getSubFieldImpl(name.c_str(), throws);
    }
    PVFieldPtr getSubFieldImpl(const char *name, bool throws) const;
    PVFieldPtr getSubFieldImpl(std::size_t fieldOffset, bool throws) const;

    PVFieldPtrArray pvFields;
    StructureConstPtr structurePtr;
    std::string extendsStructureName;
    friend class PVDataCreate;
    EPICS_NOT_COPYABLE(PVStructure)
};

epicsShareFunc
std::ostream& operator<<(std::ostream& strm, const PVStructure::Formatter& format);

class epicsShareClass PVUnion : public PVField
{
public:
    POINTER_DEFINITIONS(PVUnion);
    virtual ~PVUnion();
    typedef PVUnion & reference;
    typedef const PVUnion & const_reference;

    static const int32 UNDEFINED_INDEX;

    inline const UnionConstPtr& getUnion() const { return unionPtr; }

    inline const PVFieldPtr& get() { return value; }
    inline PVField::const_shared_pointer get() const { return value; }

    template<typename PVT>
    inline std::tr1::shared_ptr<PVT> get() {
        STATIC_ASSERT(PVT::isPVField); // only allow cast from PVField sub-class
        return std::tr1::dynamic_pointer_cast<PVT>(get());
    }

    template<typename PVT>
    inline std::tr1::shared_ptr<const PVT> get() const {
        STATIC_ASSERT(PVT::isPVField); // only allow cast from PVField sub-class
        return std::tr1::dynamic_pointer_cast<const PVT>(get());
    }

    PVFieldPtr select(int32 index);

    template<typename PVT>
    inline std::tr1::shared_ptr<PVT> select(int32 index) {
        STATIC_ASSERT(PVT::isPVField); // only allow cast from PVField sub-class
        return std::tr1::dynamic_pointer_cast<PVT>(select(index));
    }

    PVFieldPtr select(std::string const & fieldName);

    template<typename PVT>
    inline std::tr1::shared_ptr<PVT> select(std::string const & fieldName) {
        return std::tr1::dynamic_pointer_cast<PVT>(select(fieldName));
    }

    inline int32 getSelectedIndex() const { return selector; }

    std::string getSelectedFieldName() const;

    inline void set(PVFieldPtr const & value) {
        set(selector, value);
    }
    void set(int32 index, PVFieldPtr const & value);

    void set(std::string const & fieldName, PVFieldPtr const & value);

    virtual void serialize(
        ByteBuffer *pbuffer,SerializableControl *pflusher) const OVERRIDE FINAL;
    virtual void deserialize(
        ByteBuffer *pbuffer,DeserializableControl *pflusher) OVERRIDE FINAL;
    explicit PVUnion(UnionConstPtr const & punion);

    virtual std::ostream& dumpValue(std::ostream& o) const OVERRIDE FINAL;

    void copy(const PVUnion& from);
    void copyUnchecked(const PVUnion& from);

private:
    static PVDataCreatePtr pvDataCreate;

    friend class PVDataCreate;
    UnionConstPtr unionPtr; // same as PVField::getField()

        int32 selector;
        PVFieldPtr value;
        bool variant;
    EPICS_NOT_COPYABLE(PVUnion)
};


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;


    protected:
        template<typename A>
        explicit PVVectorStorage(A a) : Base(a) {}
    public:
        virtual ~PVVectorStorage(){}

        // Primitive array manipulations

        virtual const_svector view() const = 0;

        virtual void swap(const_svector& other) = 0;

        virtual void replace(const const_svector& next) = 0;

        // Derived operations

        inline svector reuse()
        {
            const_svector result;
            this->swap(result);
            return thaw(result);
        }

        EPICS_NOT_COPYABLE(PVVectorStorage)
    };
} // namespace detail

template<typename T>
class epicsShareClass 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;


    static const ScalarType typeCode;

    virtual ~PVValueArray();

    virtual ArrayConstPtr getArray() const OVERRIDE FINAL;

    virtual std::ostream& dumpValue(std::ostream& o) const OVERRIDE FINAL;
    virtual std::ostream& dumpValue(std::ostream& o, size_t index) const OVERRIDE FINAL;

    virtual size_t getLength() const OVERRIDE FINAL {return value.size();}
    virtual size_t getCapacity() const OVERRIDE FINAL {return value.capacity();}

    virtual void setCapacity(size_t capacity) OVERRIDE FINAL;
    virtual void setLength(size_t length) OVERRIDE FINAL;

    virtual const_svector view() const OVERRIDE FINAL {return value;}
    virtual void swap(const_svector &other) OVERRIDE FINAL;
    virtual void replace(const const_svector& next) OVERRIDE FINAL;

    // from Serializable
    virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const OVERRIDE FINAL;
    virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher) OVERRIDE FINAL;
    virtual void serialize(ByteBuffer *pbuffer,
                           SerializableControl *pflusher, size_t offset, size_t count) const OVERRIDE FINAL;

protected:
    virtual void _getAsVoid(epics::pvData::shared_vector<const void>& out) const OVERRIDE FINAL;
    virtual void _putFromVoid(const epics::pvData::shared_vector<const void>& in) OVERRIDE FINAL;

    explicit PVValueArray(ScalarArrayConstPtr const & scalar);
    const_svector value;
    friend class PVDataCreate;
    EPICS_NOT_COPYABLE(PVValueArray)
};


template<>
class epicsShareClass 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 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;
    virtual ~PVValueArray() {}

    virtual ArrayConstPtr getArray() const OVERRIDE FINAL
    {
        return std::tr1::static_pointer_cast<const Array>(structureArray);
    }

    virtual size_t getLength() const OVERRIDE FINAL {return value.size();}
    virtual size_t getCapacity() const OVERRIDE FINAL {return value.capacity();}

    virtual void setCapacity(size_t capacity) OVERRIDE FINAL;
    virtual void setLength(std::size_t length) OVERRIDE FINAL;

    StructureArrayConstPtr getStructureArray() const {return structureArray;}
    std::size_t append(std::size_t number);
    bool remove(std::size_t offset,std::size_t number);
    void compress();

    virtual const_svector view() const OVERRIDE FINAL { return value; }
    virtual void swap(const_svector &other) OVERRIDE FINAL;
    virtual void replace(const const_svector &other) OVERRIDE FINAL {
        checkLength(other.size());
        value = other;
        PVField::postPut();
    }

    virtual void serialize(ByteBuffer *pbuffer,
        SerializableControl *pflusher) const OVERRIDE FINAL;
    virtual void deserialize(ByteBuffer *buffer,
        DeserializableControl *pflusher) OVERRIDE FINAL;
    virtual void serialize(ByteBuffer *pbuffer,
        SerializableControl *pflusher, std::size_t offset, std::size_t count) const OVERRIDE FINAL;

    virtual std::ostream& dumpValue(std::ostream& o) const OVERRIDE FINAL;
    virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const OVERRIDE FINAL;

    void copy(const PVStructureArray& from);
    void copyUnchecked(const PVStructureArray& from);

protected:
     PVValueArray(StructureArrayConstPtr const & structureArray);
private:
    StructureArrayConstPtr structureArray;
    const_svector value;
    friend class PVDataCreate;
    EPICS_NOT_COPYABLE(PVValueArray)
};



template<>
class epicsShareClass PVValueArray<PVUnionPtr> : public detail::PVVectorStorage<PVUnionPtr,PVArray>
{
    typedef detail::PVVectorStorage<PVUnionPtr,PVArray> base_t;
public:
    POINTER_DEFINITIONS(PVUnionArray);
    typedef PVUnionPtr  value_type;
    typedef PVUnionPtr* pointer;
    typedef const PVUnionPtr* const_pointer;
    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<PVUnionPtr> svector;
    typedef ::epics::pvData::shared_vector<const PVUnionPtr> const_svector;
    virtual ~PVValueArray() {}

    virtual ArrayConstPtr getArray() const OVERRIDE FINAL
    {
        return std::tr1::static_pointer_cast<const Array>(unionArray);
    }

    virtual size_t getLength() const OVERRIDE FINAL {return value.size();}
    virtual size_t getCapacity() const OVERRIDE FINAL {return value.capacity();}

    virtual void setCapacity(size_t capacity) OVERRIDE FINAL;
    virtual void setLength(std::size_t length) OVERRIDE FINAL;

    UnionArrayConstPtr getUnionArray() const {return unionArray;}
    std::size_t append(std::size_t number);
    bool remove(std::size_t offset,std::size_t number);
    void compress();

    virtual const_svector view() const OVERRIDE { return value; }
    virtual void swap(const_svector &other) OVERRIDE;
    virtual void replace(const const_svector &other) OVERRIDE FINAL {
        checkLength(other.size());
        value = other;
        PVField::postPut();
    }

    virtual void serialize(ByteBuffer *pbuffer,
        SerializableControl *pflusher) const OVERRIDE FINAL;
    virtual void deserialize(ByteBuffer *buffer,
        DeserializableControl *pflusher) OVERRIDE FINAL;
    virtual void serialize(ByteBuffer *pbuffer,
        SerializableControl *pflusher, std::size_t offset, std::size_t count) const OVERRIDE FINAL;

    virtual std::ostream& dumpValue(std::ostream& o) const OVERRIDE FINAL;
    virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const OVERRIDE FINAL;

    void copy(const PVUnionArray& from);
    void copyUnchecked(const PVUnionArray& from);

protected:
    explicit PVValueArray(UnionArrayConstPtr const & unionArray);
private:
    UnionArrayConstPtr unionArray;
    const_svector value;
    friend class PVDataCreate;
    EPICS_NOT_COPYABLE(PVValueArray)
};


typedef PVValueArray<boolean> PVBooleanArray;
typedef std::tr1::shared_ptr<PVBooleanArray> PVBooleanArrayPtr;

typedef PVValueArray<int8> PVByteArray;
typedef std::tr1::shared_ptr<PVByteArray> PVByteArrayPtr;

typedef PVValueArray<int16> PVShortArray;
typedef std::tr1::shared_ptr<PVShortArray> PVShortArrayPtr;

typedef PVValueArray<int32> PVIntArray;
typedef std::tr1::shared_ptr<PVIntArray> PVIntArrayPtr;

typedef PVValueArray<int64> PVLongArray;
typedef std::tr1::shared_ptr<PVLongArray> PVLongArrayPtr;

typedef PVValueArray<uint8> PVUByteArray;
typedef std::tr1::shared_ptr<PVUByteArray> PVUByteArrayPtr;

typedef PVValueArray<uint16> PVUShortArray;
typedef std::tr1::shared_ptr<PVUShortArray> PVUShortArrayPtr;

typedef PVValueArray<uint32> PVUIntArray;
typedef std::tr1::shared_ptr<PVUIntArray> PVUIntArrayPtr;

typedef PVValueArray<uint64> PVULongArray;
typedef std::tr1::shared_ptr<PVULongArray> PVULongArrayPtr;

typedef PVValueArray<float> PVFloatArray;
typedef std::tr1::shared_ptr<PVFloatArray> PVFloatArrayPtr;

typedef PVValueArray<double> PVDoubleArray;
typedef std::tr1::shared_ptr<PVDoubleArray> PVDoubleArrayPtr;

typedef PVValueArray<std::string> PVStringArray;
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;

namespace detail {
struct pvfield_factory;
}

class epicsShareClass PVDataCreate {
    friend struct detail::pvfield_factory;
public:
    static const 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);
    template<typename PVT>
    std::tr1::shared_ptr<PVT> createPVScalar()
    {
        return std::tr1::static_pointer_cast<PVT>(createPVScalar(PVT::typeCode));
    }

    PVStructurePtr createPVStructure(StructureConstPtr const & structure);
    PVStructurePtr createPVStructure(
        StringArray const & fieldNames,PVFieldPtrArray const & pvFields);
    PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);

    PVUnionPtr createPVUnion(UnionConstPtr const & punion);
   PVUnionPtr createPVUnion(PVUnionPtr const & unionToClone);
    PVUnionPtr createPVVariantUnion();

    PVScalarArrayPtr createPVScalarArray(ScalarArrayConstPtr const & scalarArray);
    PVScalarArrayPtr createPVScalarArray(ScalarType elementType);
    PVScalarArrayPtr createPVScalarArray(PVScalarArrayPtr const  & scalarArrayToClone);
    template<typename PVAT>
    std::tr1::shared_ptr<PVAT> createPVScalarArray()
    {
        return std::tr1::static_pointer_cast<PVAT>(createPVScalarArray(PVAT::typeCode));
    }

    PVStructureArrayPtr createPVStructureArray(StructureArrayConstPtr const & structureArray);
    PVStructureArrayPtr createPVStructureArray(StructureConstPtr const & structure)
    {
        return createPVStructureArray(fieldCreate->createStructureArray(structure));
    }

    PVUnionArrayPtr createPVUnionArray(UnionArrayConstPtr const & unionArray);
    PVUnionArrayPtr createPVUnionArray(UnionConstPtr const & punion)
    {
        return createPVUnionArray(fieldCreate->createUnionArray(punion));
    }
    PVUnionArrayPtr createPVVariantUnionArray();

private:
   PVDataCreate();
   FieldCreatePtr fieldCreate;
   EPICS_NOT_COPYABLE(PVDataCreate)
};

FORCE_INLINE const PVDataCreatePtr& getPVDataCreate() {
    return PVDataCreate::getPVDataCreate();
}

bool epicsShareExtern operator==(const PVField&, const PVField&);

static inline bool operator!=(const PVField& a, const PVField& b)
{return !(a==b);}

}}

namespace std{
    epicsShareExtern std::ostream& operator<<(std::ostream& o, const epics::pvData::PVField *ptr);
}

#endif  /* PVDATA_H */