| /******************************************************************************* |
| * Copyright (c) 2005 - 2013 Profactor GmbH, ACIN, nxtcontrol GmbH, fortiss GmbH, 2018 TU Vienna/ACIN |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Thomas Strasser, Ingomar Müller, Alois Zoitl, Gerhard Ebenhofer, |
| * Ingo Hegny, Martin Melik Merkumians, Stanislav Meduna, Monika Wenger |
| * - initial implementation and rework communication infrastructure |
| * Martin Melik Merkumians - templated cast factory function |
| *******************************************************************************/ |
| #ifndef _ANY_H_ |
| #define _ANY_H_ |
| |
| #include <string.h> |
| #include "../typelib.h" |
| #include "iec61131_cast_helper.h" |
| |
| #if (!defined FORTE_LITTLE_ENDIAN) && (!defined FORTE_BIG_ENDIAN) |
| # error "Endianess is not defined!" |
| #endif |
| |
| /*!\ingroup COREDTS CIEC_ANY represents the IEC_ANY data type according to IEC 61131. |
| */ |
| |
| /*!\ingroup CORE \defgroup COREDTS Core Data Types |
| * \brief Implementation of the core IEC 61131-3 data types. |
| * |
| */ |
| |
| class CIEC_ANY_REAL; |
| class CIEC_ANY_BIT; |
| |
| class CIEC_ANY{ |
| public: |
| /*! \ingroup COREDTS\brief Data type ID's are chosen according to IEC 61499-1 : Function Block |
| * -- Part 1 Architecture - Annex F (informative) Information exchange/F.3 |
| * Transfer syntaxes (page 89). |
| */ |
| enum EDataTypeID{ |
| e_ANY, e_BOOL, e_SINT, e_INT, e_DINT, e_LINT, e_USINT, e_UINT, e_UDINT, e_ULINT, e_BYTE, e_WORD, e_DWORD, e_LWORD, e_DATE, e_TIME_OF_DAY, e_DATE_AND_TIME, e_TIME, //until here simple Datatypes |
| e_REAL, |
| e_LREAL, |
| e_STRING, |
| e_WSTRING, |
| e_DerivedData, |
| e_DirectlyDerivedData, |
| e_EnumeratedData, |
| e_SubrangeData, |
| e_ARRAY, //according to the compliance profile |
| e_STRUCT, |
| e_External = 256, // Base for CIEC_ANY based types outside of the forte base |
| e_Max = 65535 // Guarantees at least 16 bits - otherwise gcc will optimizes on some platforms |
| }; |
| |
| // ordering of sizes is according to EDataTypeID, that the ID can be used to get the proper value, +1 for \0 |
| const static TForteByte csmStringBufferSize[]; |
| |
| #ifdef FORTE_USE_64BIT_DATATYPES |
| typedef TForteUInt64 TLargestUIntValueType; |
| typedef TForteInt64 TLargestIntValueType; |
| #else |
| typedef TForteUInt32 TLargestUIntValueType; |
| typedef TForteInt32 TLargestIntValueType; |
| #endif |
| |
| /* the following functions have to be added by hand as they the default DECLARE_FIRMWARE_DATATYPE and DEFINE_FIRMWARE_DATATYPE |
| * does not work here. |
| */ |
| static CIEC_ANY *createDataType(TForteByte *pa_acDataBuf){ |
| return (0 != pa_acDataBuf) ? new (pa_acDataBuf) CIEC_ANY : new CIEC_ANY; |
| } |
| const static CTypeLib::CDataTypeEntry csmFirmwareDataTypeEntry_CIEC_ANY; |
| |
| static int dummyInit(); |
| |
| template<typename U, typename T> |
| static typename forte::core::mpl::implicit_or_explicit_cast<T, U>::type cast(const T paFromCast){ |
| U oToCast; |
| if (forte::core::mpl::is_base_of<CIEC_ANY_BIT, T>::value || |
| forte::core::mpl::is_base_of<CIEC_ANY_BIT, U>::value) { |
| oToCast.setValueSimple(paFromCast); |
| } else |
| if(forte::core::mpl::is_base_of<CIEC_ANY_REAL, T>::value){ |
| specialCast(paFromCast, oToCast); |
| } else if(forte::core::mpl::is_base_of<CIEC_ANY_REAL, U>::value){ |
| oToCast.setValue(paFromCast); |
| } |
| else{ |
| oToCast.setValueSimple(paFromCast); |
| } |
| return oToCast; |
| } |
| |
| CIEC_ANY() : |
| mForced(false){ |
| setLargestUInt(0); |
| } |
| |
| virtual ~CIEC_ANY(){ |
| } |
| |
| void saveAssign(const CIEC_ANY &pa_roValue); |
| |
| /*! \brief Set method for data type member value |
| * |
| * The data type value is set through the copy assignment |
| * |
| */ |
| virtual void setValue(const CIEC_ANY &pa_roValue){ |
| setValueSimple(pa_roValue); |
| } |
| |
| /*! \brief Makes a clone of the data type object |
| * |
| * With this command a clone object of the actual data type object is created. |
| * This clone object is necessary for establishing data-connections. |
| * Pure virtual function implementation. |
| */ |
| virtual CIEC_ANY* clone(TForteByte *pa_acDataBuf) const { |
| return createDataType(pa_acDataBuf); //there is nothing to clone in any impl |
| } |
| |
| /*! \brief Get data type id method |
| * |
| * With this command the data type of the actual object can be identified. |
| * The data type identifier is unique for each data type within FORTE. |
| */ |
| virtual EDataTypeID getDataTypeID() const { |
| return CIEC_ANY::e_ANY; |
| } |
| |
| virtual CStringDictionary::TStringId getTypeNameID() const { |
| return csmFirmwareDataTypeEntry_CIEC_ANY.getTypeNameId(); |
| } |
| |
| /*! \brief Get the pointer to the union char array |
| * |
| * This command returns the pointer to the union char array |
| * \return Returns TForteByte* |
| */ |
| |
| TForteByte* getDataPtr(){ |
| return mAnyData.mData; |
| } |
| |
| /*! \brief Get a const pointer to the union char array |
| * |
| * \return Returns const TForteByte* |
| */ |
| |
| const TForteByte* getConstDataPtr() const{ |
| return mAnyData.mData; |
| } |
| |
| /*! \brief Converts string value to data type value |
| * |
| * This command implements a conversion function from IEC61131 |
| * data type (string format) to a C++ conform type. |
| * This function is necessary for communication with a proper engineering system. |
| * Pure virtual function implementation. |
| * \param pa_pacValue string buffer |
| * \return number of bytes taken used from the buffer |
| * -1 on on error |
| */ |
| virtual int fromString(const char *pa_pacValue); |
| |
| /*! \brief Converts data type value to string |
| * |
| * This command implements a conversion function from C++ data type |
| * to IEC61131 conform data type (string format). |
| * This function is necessary for communication with a proper engineering system. |
| * Pure virtual function implementation. |
| * \param pa_pacValue buffer for storing the string representation |
| * \param pa_nBufferSize size in bytes available in the buffer |
| * \return number of bytes used in the buffer without trailing 0x00 |
| * -1 on error |
| */ |
| virtual int toString(char* paValue, size_t paBufferSize) const; |
| |
| /*! \brief determine whether we can cast the source to the destination and what kind of cast it is |
| */ |
| static bool isCastable(EDataTypeID pa_eSource, EDataTypeID pa_eDestination, bool &pa_rbUpCast, bool &pa_rbDownCast); |
| static bool isCastable(EDataTypeID pa_eSource, EDataTypeID pa_eDestination){ |
| bool bUpCast, bDownCast; |
| return isCastable(pa_eSource, pa_eDestination, bUpCast, bDownCast); |
| } |
| |
| /*! \brief perform special cast operation that can not be directly handled by the data types |
| */ |
| static void specialCast(const CIEC_ANY &pa_roSrcValue, CIEC_ANY &pa_roDstValue); |
| |
| /*! \brief calculates buffer size needed for toString conversion |
| */ |
| virtual size_t getToStringBufferSize() const; |
| |
| #ifdef FORTE_SUPPORT_CUSTOM_SERIALIZABLE_DATATYPES |
| /*! \brief the following methods have to be implemented if a custom datatype is added to the forte which is not supported by the default seralize mechanism. */ |
| /*! \brief returns the required size for serialization */ |
| virtual unsigned int getRequiredSerializationSize() const{ |
| return 0; |
| } |
| ; |
| /*! \brief returns the tag of the datatype for serialization */ |
| virtual TForteByte getTag() const{ |
| return 0xFF; |
| } |
| ; |
| /*! \brief serialize the custom type */ |
| virtual int serializeCustomType(TForteByte*, int) const{ |
| return -1; |
| } |
| ; |
| /*! \brief deserialize the tag */ |
| virtual bool deserializeTag(const TForteByte){ |
| return false; |
| } |
| ; |
| /*! \brief deserialize the custom type*/ |
| virtual int deserializeCustomType(const TForteByte*, int){ |
| return -1; |
| } |
| ; |
| #endif |
| |
| bool isForced() const{ |
| return mForced; |
| } |
| |
| void setForced(bool pa_bForced){ |
| mForced = pa_bForced; |
| } |
| |
| protected: |
| /*! \brief copy the union data |
| * |
| * To be used for efficiently implementing assignment operators where it is |
| * known that this can be done safely. |
| */ |
| inline |
| void setValueSimple(const CIEC_ANY &pa_roValue){ |
| mAnyData = pa_roValue.mAnyData; |
| } |
| |
| /*! \brief Get Method for complex datatypes |
| * A virtual function for datatypes who can't be copied by the union assignment |
| */ |
| |
| void setTBOOL8(bool src){ |
| mAnyData.mLargestUInt = TLargestUIntValueType(src); |
| } |
| |
| void setTUINT32(TForteUInt32 src){ //also used for TForteDWord |
| mAnyData.mLargestUInt = TLargestUIntValueType(src); |
| } |
| |
| void setTUINT16(TForteUInt16 src){ //also used for TForteWord |
| mAnyData.mLargestUInt = TLargestUIntValueType(src); |
| } |
| |
| void setTUINT8(TForteUInt8 src){ //also used for TForteByte |
| mAnyData.mLargestUInt = TLargestUIntValueType(src); |
| } |
| |
| void setTINT32(TForteInt32 src){ |
| mAnyData.mLargestInt = TLargestIntValueType(src); |
| } |
| |
| void setTINT16(TForteInt16 src){ |
| mAnyData.mLargestInt = TLargestIntValueType(src); |
| } |
| |
| void setTINT8(TForteInt8 src){ |
| mAnyData.mLargestInt = TLargestIntValueType(src); |
| } |
| |
| #ifdef FORTE_USE_REAL_DATATYPE |
| void setTFLOAT(TForteFloat src){ |
| mAnyData.mFloat = TForteFloat(src); |
| } |
| #endif //#ifdef FORTE_USE_REAL_DATATYPE |
| #ifdef FORTE_USE_LREAL_DATATYPE |
| void setTDFLOAT(TForteDFloat src){ |
| mAnyData.mDFloat = TForteDFloat(src); |
| } |
| #endif //#ifdef FORTE_USE_LREAL_DATATYPE |
| |
| #ifdef FORTE_USE_64BIT_DATATYPES |
| |
| void setTUINT64(TForteUInt64 src){ //also used for LWORD |
| mAnyData.mLargestUInt = TLargestUIntValueType(src); |
| } |
| |
| void setTINT64(TForteInt64 src){ |
| mAnyData.mLargestInt = TLargestIntValueType(src); |
| } |
| #endif //#ifdef FORTE_USE_64BIT_DATATYPES |
| #ifdef FORTE_BIG_ENDIAN |
| bool getTBOOL8() const{ |
| return (mAnyData.mLargestUInt != 0); |
| } |
| TForteUInt32 getTUINT32() const{ //also used for TForteDWord |
| return (TForteUInt32)mAnyData.mLargestUInt; |
| } |
| |
| TForteUInt16 getTUINT16() const{ //also used for TForteWord |
| return (TForteUInt16)mAnyData.mLargestUInt; |
| } |
| |
| TForteUInt8 getTUINT8() const{ //also used for TForteByte |
| return (TForteUInt8)mAnyData.mLargestUInt; |
| } |
| |
| TForteInt32 getTINT32() const{ |
| return (TForteInt32)mAnyData.mLargestInt; |
| } |
| |
| TForteInt16 getTINT16() const{ |
| return (TForteInt16)mAnyData.mLargestInt; |
| } |
| |
| TForteInt8 getTINT8() const{ |
| return (TForteInt8)mAnyData.mLargestInt; |
| } |
| |
| #ifdef FORTE_USE_64BIT_DATATYPES |
| TForteUInt64 getTUINT64() const{ //also used for LWORD |
| return (TForteUInt64)mAnyData.mLargestUInt; |
| } |
| TForteInt64 getTINT64() const{ |
| return (TForteInt64)mAnyData.mLargestInt; |
| } |
| #endif //#ifdef FORTE_USE_64BIT_DATATYPES |
| #else |
| #ifdef FORTE_LITTLE_ENDIAN |
| bool getTBOOL8() const{ |
| return mAnyData.mBool; |
| } |
| TForteUInt32 getTUINT32() const{ //also used for TForteDWord |
| return mAnyData.mUInt32; |
| } |
| TForteUInt16 getTUINT16() const{ //also used for TForteWord |
| return mAnyData.mUInt16; |
| } |
| TForteUInt8 getTUINT8() const{ //also used for TForteByte |
| return mAnyData.mUInt8; |
| } |
| TForteInt32 getTINT32() const{ |
| return mAnyData.mInt32; |
| } |
| TForteInt16 getTINT16() const{ |
| return mAnyData.mInt16; |
| } |
| TForteInt8 getTINT8() const{ |
| return mAnyData.mInt8; |
| } |
| |
| #ifdef FORTE_USE_64BIT_DATATYPES |
| TForteUInt64 getTUINT64() const{ //also used for LWORD |
| return mAnyData.mUInt64; |
| } |
| TForteInt64 getTINT64() const{ |
| return mAnyData.mInt64; |
| } |
| #endif //#ifdef FORTE_USE_64BIT_DATATYPES |
| #else |
| #error Endianess not defined! |
| #endif //#ifdef FORTE_BIG_ENDIAN |
| #endif //#ifdef FORTE_LITTLE_ENDIAN |
| #ifdef FORTE_USE_REAL_DATATYPE //!< get-Methods are Big/Little Endian independent |
| TForteFloat getTFLOAT() const{ |
| return (TForteFloat) mAnyData.mFloat; |
| } |
| #endif //#ifdef FORTE_USE_REAL_DATATYPE |
| #ifdef FORTE_USE_LREAL_DATATYPE |
| TForteDFloat getTDFLOAT() const{ |
| return TForteDFloat(mAnyData.mDFloat); |
| } |
| #endif //#ifdef FORTE_USE_LREAL_DATATYPE |
| |
| TLargestUIntValueType getLargestUInt() const{ |
| return mAnyData.mLargestUInt; |
| } |
| |
| void setLargestUInt(TLargestUIntValueType paVal){ |
| mAnyData.mLargestUInt = paVal; |
| } |
| |
| TLargestIntValueType getLargestInt() const{ |
| return mAnyData.mLargestInt; |
| } |
| |
| void setLargestInt(TLargestIntValueType paVal){ |
| mAnyData.mLargestInt = paVal; |
| } |
| |
| TForteByte *getGenData(){ |
| return mAnyData.mGenData; |
| } |
| |
| const TForteByte *getGenData() const{ |
| return mAnyData.mGenData; |
| } |
| |
| void setGenData(TForteByte *paGenData){ |
| mAnyData.mGenData = paGenData; |
| } |
| |
| static CStringDictionary::TStringId parseTypeName(const char *pa_pacValue, const char *pa_pacHashPos); |
| |
| private: |
| const static int scmMaxTypeNameLength = 14; |
| static const char scmAnyToStringResponse[]; |
| |
| //!declared but undefined copy constructor as we don't want ANYs to be directly copied. |
| CIEC_ANY(const CIEC_ANY&); |
| |
| //!declared but undefined copy constructor as we don't want ANYs to be directly assigned. Can result in problems for more complicated data types (e.g., string) |
| CIEC_ANY& operator =(const CIEC_ANY& pa_roValue); |
| |
| bool mForced; |
| |
| //Anonymous union holding the data value of our IEC data type |
| union UAnyData{ |
| bool mBool; |
| |
| TForteByte mByte; |
| TForteWord mWord; |
| TForteDWord mDWord; |
| |
| TForteInt8 mInt8; |
| TForteInt16 mInt16; |
| TForteInt32 mInt32; |
| |
| TForteUInt8 mUInt8; |
| TForteUInt16 mUInt16; |
| TForteUInt32 mUInt32; |
| |
| #ifdef FORTE_USE_REAL_DATATYPE |
| TForteFloat mFloat; |
| #endif //#ifdef FORTE_USE_REAL_DATATYPE |
| #ifdef FORTE_USE_LREAL_DATATYPE |
| TForteDFloat mDFloat; |
| #endif //#ifdef FORTE_USE_LREAL_DATATYPE |
| #ifdef FORTE_USE_64BIT_DATATYPES |
| TForteInt64 mInt64; |
| TForteUInt64 mUInt64; |
| TForteByte mData[sizeof(TForteUInt64)]; //!< For data extraction in big endian machines |
| #else |
| TForteByte mData[sizeof(TForteUInt32)]; //!< For data extraction in big endian machines |
| #endif //#ifdef FORTE_USE_64BIT_DATATYPES |
| TLargestUIntValueType mLargestUInt; |
| TLargestIntValueType mLargestInt; |
| /*! \brief A pointer to general data that can be used for data types needing other data than that contained in the union |
| * |
| * This is needed as the current design does not allow that the size of data types when created is different from |
| * the size of the CIEC_ANY class. This data value will be used for example by string or array. |
| */ |
| TForteByte *mGenData; |
| }; |
| |
| UAnyData mAnyData; |
| |
| }; |
| |
| /*!\brief Type for handling CIEC_ANY pointers |
| */ |
| typedef CIEC_ANY* TIEC_ANYPtr; |
| typedef const CIEC_ANY* TConstIEC_ANYPtr; |
| |
| typedef CIEC_ANY IIEC_ANY; //TODO: for legacy support, will be deleted with next major release |
| |
| #endif /*_MANY_H_*/ |