| /******************************************************************************* |
| * Copyright (c) 2005 - 2015 ACIN, Profactor GmbH, fortiss GmbH |
| * 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: |
| * Alois Zoitl, Thomas Strasser, Smodic Rene, Gerhard Ebenhofer, |
| * Ingo Hegny, Monika Wenger |
| * - initial implementation and rework communication infrastructure |
| *******************************************************************************/ |
| #include "./datatypes/forte_any.h" |
| #include "typelib.h" |
| #include "eventconn.h" |
| #include "dataconn.h" |
| #include "adapterconn.h" |
| #include "resource.h" |
| #include "if2indco.h" |
| #include <stddef.h> |
| |
| CTypeLib::CTypeEntry::CTypeEntry(CStringDictionary::TStringId pa_nTypeNameId) : |
| m_nTypeNameId(pa_nTypeNameId), |
| m_poNext(0){ |
| } |
| |
| CTypeLib::CTypeEntry::~CTypeEntry(void){ |
| |
| } |
| |
| CTypeLib::CSpecTypeEntry::CSpecTypeEntry(CStringDictionary::TStringId pa_nTypeNameId, const SFBInterfaceSpec* paSocketInterfaceSpec) : |
| CTypeEntry(pa_nTypeNameId), |
| mSocketInterfaceSpec(paSocketInterfaceSpec){ |
| } |
| |
| CTypeLib::CSpecTypeEntry::~CSpecTypeEntry(void){ |
| |
| } |
| |
| CTypeLib::CFBTypeEntry::CFBTypeEntry(CStringDictionary::TStringId pa_nTypeNameId, TFunctionBlockCreateFunc pa_pfuncCreateFB, const SFBInterfaceSpec* paSocketInterfaceSpec): |
| CSpecTypeEntry(pa_nTypeNameId, paSocketInterfaceSpec), |
| m_pfuncFBCreationFunc(pa_pfuncCreateFB){ |
| CTypeLib::addFBType(this); |
| |
| } |
| |
| |
| CTypeLib::CFBTypeEntry::~CFBTypeEntry(void){ |
| |
| } |
| |
| CTypeLib::CAdapterTypeEntry::CAdapterTypeEntry(CStringDictionary::TStringId pa_nTypeNameId, TAdapterCreateFunc pa_pfuncCreateAdapter, const SFBInterfaceSpec* paSocketInterfaceSpec): |
| CSpecTypeEntry(pa_nTypeNameId, paSocketInterfaceSpec), |
| m_pfuncAdapterCreationFunc(pa_pfuncCreateAdapter){ |
| CTypeLib::addAdapterType(this); |
| |
| } |
| |
| CTypeLib::CAdapterTypeEntry::~CAdapterTypeEntry(void){ |
| |
| } |
| |
| CTypeLib::CDataTypeEntry::CDataTypeEntry(CStringDictionary::TStringId paTypeNameId, TDataTypeCreateFunc pafuncDTCreateFunc) : |
| CTypeEntry(paTypeNameId), m_pfuncDTCreateFunc(pafuncDTCreateFunc) { |
| CTypeLib::addDataType(this); |
| } |
| |
| CTypeLib::CDataTypeEntry::~CDataTypeEntry(void){ |
| |
| } |
| |
| |
| EMGMResponse CTypeLib::m_eLastErrorMSG = e_RDY; |
| |
| CTypeLib::CFBTypeEntry *CTypeLib::m_poFBLibStart = 0; |
| CTypeLib::CFBTypeEntry *CTypeLib::m_poFBLibEnd = 0; |
| |
| CTypeLib::CAdapterTypeEntry *CTypeLib::m_poAdapterLibStart = 0; |
| CTypeLib::CAdapterTypeEntry *CTypeLib::m_poAdapterLibEnd = 0; |
| |
| CTypeLib::CDataTypeEntry *CTypeLib::m_poDTLibStart = 0; |
| CTypeLib::CDataTypeEntry *CTypeLib::m_poDTLibEnd = 0; |
| |
| CTypeLib::CTypeEntry *CTypeLib::findType(CStringDictionary::TStringId pa_nTypeId, CTypeLib::CTypeEntry *pa_poListStart) { |
| CTypeEntry *retval = 0; |
| for (CTypeEntry *poRunner = pa_poListStart; poRunner != 0; poRunner |
| = poRunner->m_poNext){ |
| if (pa_nTypeId == poRunner->getTypeNameId()) { |
| retval = poRunner; |
| break; |
| } |
| } |
| return retval; |
| } |
| |
| CAdapter *CTypeLib::createAdapter(CStringDictionary::TStringId pa_nInstanceNameId, CStringDictionary::TStringId pa_nAdapterTypeId, CResource *pa_poRes, bool pa_bIsPlug) { |
| CAdapter *poNewAdapter = 0; |
| CTypeEntry *poToCreate = findType(pa_nAdapterTypeId, m_poAdapterLibStart); |
| if (0 != poToCreate) { |
| poNewAdapter = |
| (static_cast<CAdapterTypeEntry *>(poToCreate))->createAdapterInstance(pa_nInstanceNameId,pa_poRes, pa_bIsPlug); |
| if(0 == poNewAdapter) { |
| m_eLastErrorMSG = e_OVERFLOW; |
| } |
| } //no generic adapters supported |
| |
| return poNewAdapter; |
| |
| } |
| |
| CFunctionBlock *CTypeLib::createFB(CStringDictionary::TStringId pa_nInstanceNameId, CStringDictionary::TStringId pa_nFBTypeId, CResource *pa_poRes) { |
| CFunctionBlock *poNewFB = 0; |
| CTypeEntry *poToCreate = findType(pa_nFBTypeId, m_poFBLibStart); |
| //TODO: Avoid that the user can create generic blocks. |
| if (0 != poToCreate) { |
| poNewFB |
| = (static_cast<CFBTypeEntry *>(poToCreate))->createFBInstance(pa_nInstanceNameId, pa_poRes); |
| if(0 == poNewFB) { // we could not create the requested object |
| m_eLastErrorMSG = e_OVERFLOW; |
| } |
| } else { //check for parameterizable FBs (e.g. SERVER) |
| TIdentifier acGenFBName = { "GEN_" }; |
| const char *acTypeBuf = CStringDictionary::getInstance().get(pa_nFBTypeId); |
| const char *pcUnderScore = getFirstNonTypeNameUnderscorePos(acTypeBuf); |
| |
| if (0 != pcUnderScore) { // We found no underscore in the type name therefore it can not be a generic type |
| ptrdiff_t nCopyLen = pcUnderScore - acTypeBuf; |
| if(nCopyLen > static_cast<ptrdiff_t>(cg_nIdentifierLength - 4)) { |
| nCopyLen = cg_nIdentifierLength - 4; |
| } |
| memcpy(&(acGenFBName[4]), acTypeBuf, nCopyLen); |
| acGenFBName[cg_nIdentifierLength] = '\0'; |
| poToCreate = findType(CStringDictionary::getInstance().getId(acGenFBName), m_poFBLibStart); |
| if (0 != poToCreate) { |
| poNewFB = (static_cast<CFBTypeEntry *>(poToCreate))->createFBInstance(pa_nInstanceNameId, pa_poRes); |
| if (0 == poNewFB){ // we could not create the requested object |
| m_eLastErrorMSG = e_OVERFLOW; |
| } |
| else { // we got a configurable block |
| if (!poNewFB->configureFB(acTypeBuf)) { |
| //TODO: Handle an error, if the FB was not configured correctly!!!! |
| } |
| } |
| } |
| else{ |
| m_eLastErrorMSG = e_UNSUPPORTED_TYPE; |
| } |
| } |
| else{ |
| m_eLastErrorMSG = e_UNSUPPORTED_TYPE; |
| } |
| } |
| |
| if(0 != poNewFB){ |
| // perform reset to move it into idle state and set the initial values |
| poNewFB->changeFBExecutionState(cg_nMGM_CMD_Reset); |
| } |
| |
| return poNewFB; |
| } |
| |
| bool CTypeLib::deleteFB(CFunctionBlock *pa_poFBToDelete) { |
| delete pa_poFBToDelete; |
| return true; |
| } |
| |
| CIEC_ANY *CTypeLib::createDataTypeInstance(CStringDictionary::TStringId pa_nDTNameId, TForteByte *pa_acDataBuf) { |
| CIEC_ANY *poNewDT = 0; |
| CTypeEntry *poToCreate = findType(pa_nDTNameId, m_poDTLibStart); |
| if (0 != poToCreate) { |
| poNewDT = (static_cast<CDataTypeEntry *>(poToCreate))->createDataTypeInstance(pa_acDataBuf); |
| if(0 == poNewDT) { // we could not create the requested object |
| m_eLastErrorMSG = e_OVERFLOW; |
| } |
| } else { |
| m_eLastErrorMSG = e_UNSUPPORTED_TYPE; |
| } |
| |
| return poNewDT; |
| } |
| |
| void CTypeLib::addFBType(CFBTypeEntry *pa_poFBTypeEntry) { |
| if (0 == findType(pa_poFBTypeEntry->getTypeNameId(), m_poFBLibStart)) { |
| if(m_poFBLibStart == 0) { |
| m_poFBLibStart = pa_poFBTypeEntry; |
| } else { |
| m_poFBLibEnd->m_poNext = pa_poFBTypeEntry; |
| } |
| m_poFBLibEnd = pa_poFBTypeEntry; |
| } |
| } |
| |
| void CTypeLib::addAdapterType(CAdapterTypeEntry *pa_poAdapterTypeEntry) { |
| if (0 == findType(pa_poAdapterTypeEntry->getTypeNameId(), m_poAdapterLibStart)) { |
| if(m_poAdapterLibStart == 0) { |
| m_poAdapterLibStart = pa_poAdapterTypeEntry; |
| } else { |
| m_poAdapterLibEnd->m_poNext = pa_poAdapterTypeEntry; |
| } |
| m_poAdapterLibEnd = pa_poAdapterTypeEntry; |
| } |
| } |
| |
| |
| void CTypeLib::addDataType(CDataTypeEntry *pa_poDTEntry) { |
| if (0 == findType(pa_poDTEntry->getTypeNameId(), m_poDTLibStart)) { |
| if(m_poDTLibStart == 0) { |
| m_poDTLibStart = pa_poDTEntry; |
| } else { |
| m_poDTLibEnd->m_poNext = pa_poDTEntry; |
| } |
| m_poDTLibEnd = pa_poDTEntry; |
| } |
| } |
| |
| |
| const char *CTypeLib::getFirstNonTypeNameUnderscorePos(const char *pa_acTypeName){ |
| const char* acRetVal = pa_acTypeName; |
| |
| do{ |
| acRetVal = strchr(acRetVal, '_'); |
| if(0 != acRetVal){ |
| if(forte::core::util::isDigit(*(acRetVal + 1))){ |
| //only when the element after the underscore is a digit it is a correct type name |
| break; |
| } |
| acRetVal++; |
| } |
| } while(0 != acRetVal); |
| |
| return acRetVal; |
| } |
| |