blob: 6dde258cbfb9e5833473da06d2bbe9569cf42dd5 [file] [log] [blame]
/*******************************************************************************
* 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;
}