blob: f8fc4efb0b60fb81985a2bc130fa199d703a0cda [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 - 2015 ACIN, 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:
* Ingo Hegny, Alois Zoitl
* - initial implementation and rework communication infrastructure
*******************************************************************************/
#include "forte_struct.h"
#ifdef FORTE_ENABLE_GENERATED_SOURCE_CPP
#include "forte_struct_gen.cpp"
#endif
#include <stdlib.h>
#ifdef FORTE_SUPPORT_ARRAYS
# include "forte_array.h"
#endif
CIEC_STRUCT::CIEC_STRUCT(CStringDictionary::TStringId paTypeName, TForteUInt16 paLength, const CStringDictionary::TStringId paElementTypes[],
const CStringDictionary::TStringId paElementNames[], TForteUInt8 paTypeID, TStructInitialValues *paInitialValues) {
setup(paTypeName, paLength, paElementTypes, paElementNames, paTypeID, paInitialValues);
}
CIEC_STRUCT::CIEC_STRUCT(const CIEC_STRUCT& paValue) :
CIEC_ANY_DERIVED() {
if(0 != paValue.getStructSize()) {
setGenData(
reinterpret_cast<TForteByte*>(new CStructSpecs(paValue.getStructTypeNameID(), paValue.getStructSize(), paValue.elementNames(),
paValue.getASN1StructType())));
CIEC_ANY *localMembers = getMembers();
const CIEC_ANY* sourceMembers = paValue.getMembers();
for(size_t i = 0; i < getStructSize(); ++i) {
sourceMembers[i].clone(reinterpret_cast<TForteByte *>(&(localMembers[i]))); //clone is faster than the CTypeLib call
}
}
}
CIEC_STRUCT::~CIEC_STRUCT(){
clear();
}
void CIEC_STRUCT::setup(CStringDictionary::TStringId paTypeName, TForteUInt16 paLength, const CStringDictionary::TStringId paElementTypes[],
const CStringDictionary::TStringId paElementNames[], TForteUInt8 paTypeID, TStructInitialValues *paInitialValues) {
if(0 != paLength) {
setGenData(reinterpret_cast<TForteByte*>(new CStructSpecs(paTypeName, paLength, paElementNames, paTypeID)));
CIEC_ANY* localMembers = getMembers();
for(size_t i = 0; i < paLength; ++i) {
CIEC_ANY *retVal = CTypeLib::createDataTypeInstance(*paElementTypes, reinterpret_cast<TForteByte *>(&(localMembers[i])));
++paElementTypes;
if(0 != retVal) {
#ifdef FORTE_SUPPORT_ARRAYS
if(g_nStringIdARRAY == paElementTypes[-1]) {
//For an array we have to do more
(static_cast<CIEC_ARRAY *>(retVal))->setup(static_cast<TForteUInt16>(*paElementTypes), paElementTypes[1]);
paElementTypes += 2;
}
#endif
if(paInitialValues && paInitialValues[i]) {
retVal->fromString(paInitialValues[i]);
}
} else { //datatype not found, clear everything and return
clear();
break;
}
}
}
}
void CIEC_STRUCT::setValue(const CIEC_ANY& paValue){
if(paValue.getDataTypeID() == e_STRUCT && (getStructTypeNameID() == static_cast<const CIEC_STRUCT&>(paValue).getStructTypeNameID())){
CIEC_ANY *localMembers = getMembers();
const CIEC_ANY* srcMembers = static_cast<const CIEC_STRUCT&>(paValue).getMembers();
for(size_t i = 0; i < getStructSize(); ++i) {
localMembers[i].setValue(srcMembers[i]);
}
}
}
void CIEC_STRUCT::clear() {
if(0 != getGenData()) {
delete getSpecs();
setGenData(0);
}
}
int CIEC_STRUCT::fromString(const char *paValue){
int nRetVal = -1;
if('(' == paValue[0]){
const char *pcRunner = paValue;
bool errorOcurred = false;
pcRunner++;
while(('\0' != *pcRunner) && (')' != *pcRunner) && !errorOcurred) {
//first extract the element name
int nLength = 0;
CStringDictionary::TStringId unElementNameId = parseNextElementId(pcRunner, nLength);
if(CStringDictionary::scm_nInvalidStringId != unElementNameId) {
pcRunner += nLength;
CIEC_ANY *poMember = getMemberNamed(unElementNameId);
if(0 != poMember) {
if(!initializeFromString(&nLength, poMember, &pcRunner, &errorOcurred)) {
break;
}
} else {
errorOcurred = true;
}
}else{
errorOcurred = true;
}
pcRunner++;
}
if(')' == *pcRunner && !errorOcurred) {
//structs have to have an opening and a closing round bracket
nRetVal = static_cast<int>(pcRunner - paValue + 1); //+1 from the closing round bracket
}
}
return nRetVal;
}
bool CIEC_STRUCT::initializeFromString(int *paLength, CIEC_ANY *paMember, const char** paRunner, bool* paErrorOcurred) {
bool retVal = true;
*paLength = paMember->fromString(*paRunner);
if(0 < *paLength) {
*paRunner += *paLength;
findNextNonBlankSpace(paRunner);
if(',' != **paRunner) {
retVal = false;
}
} else {
//we have an error or the end bracket
*paErrorOcurred = true;
}
return retVal;
}
CStringDictionary::TStringId CIEC_STRUCT::parseNextElementId(const char *paRunner, int &paCounter){
CStringDictionary::TStringId unElementNameId = CStringDictionary::scm_nInvalidStringId;
TIdentifier acIdentifier;
//remove any leading whitespaces before the identifier
while(' ' == *paRunner){
paRunner++;
paCounter++;
}
for(size_t i = 0; (('\0' != *paRunner) && (')' != *paRunner)); ++i, ++paCounter, ++paRunner) {
if(i >= cg_nIdentifierLength){
//currently we only allow identifiers smaller that size
return CStringDictionary::scm_nInvalidStringId;
}
if((':' == *paRunner) || (' ' == *paRunner)){
acIdentifier[i] = '\0'; //close identifier string
break;
}
acIdentifier[i] = *paRunner;
}
//remove any whitespaces between identifier and assignment operator
while(' ' == *paRunner){
paRunner++;
paCounter++;
}
if(':' == *paRunner){
//only if we have a : we have a correct identifier
paRunner++;
paCounter++;
if('=' == *paRunner){
unElementNameId = CStringDictionary::getInstance().getId(acIdentifier);
paRunner++;
paCounter++;
//remove any whitespaces between assignment operator and value
while(' ' == *paRunner){
paRunner++;
paCounter++;
}
if(('\0' == *paRunner) || (')' == *paRunner)){
return CStringDictionary::scm_nInvalidStringId;
}
}
}
return unElementNameId;
}
int CIEC_STRUCT::toString(char* paValue, size_t paBufferSize) const {
int nBytesUsed = -1;
if(paBufferSize) {
*paValue = '(';
paValue++;
paBufferSize--;
nBytesUsed = 1;
TForteUInt16 unSize = getStructSize();
const CStringDictionary::TStringId *punMemberNameIds = elementNames();
const CIEC_ANY *poMembers = getMembers();
for(size_t i = 0; i < unSize; ++i, ++poMembers, ++punMemberNameIds) {
const char *acMemberName = CStringDictionary::getInstance().get(*punMemberNameIds);
int nUsedBytesByElement;
if(strlen(acMemberName) + 2 > paBufferSize){
return -1;
}
strncpy(paValue, acMemberName, strlen(acMemberName));
paValue += strlen(acMemberName);
*paValue = ':';
paValue++;
*paValue = '=';
paValue++;
paBufferSize -= strlen(acMemberName) + 2;
nBytesUsed += static_cast<int>(strlen(acMemberName) + 2);
nUsedBytesByElement = poMembers->toString(paValue, paBufferSize);
if(-1 == nUsedBytesByElement){
return -1;
}
paBufferSize -= nUsedBytesByElement;
paValue += nUsedBytesByElement;
if(!paBufferSize){
return -1;
}
nBytesUsed += nUsedBytesByElement;
if(i != static_cast<size_t>(unSize - 1)) {
*paValue = ',';
paValue++;
++nBytesUsed;
paBufferSize--;
}
}
if(paBufferSize < 2){
return -1;
}
*paValue = ')';
paValue[1] = '\0';
nBytesUsed++;
}
return nBytesUsed;
}
CIEC_ANY *CIEC_STRUCT::getMemberNamed(CStringDictionary::TStringId paMemberNameId){
CIEC_ANY *poRetVal = 0;
CIEC_ANY *poMembers = getMembers();
const CStringDictionary::TStringId *punMemberNameIds = elementNames();
for(size_t i = 0; i < getStructSize(); ++i, ++poMembers, ++punMemberNameIds) {
if(*punMemberNameIds == paMemberNameId){
poRetVal = poMembers;
break;
}
}
return poRetVal;
}
size_t CIEC_STRUCT::getToStringBufferSize() const {
size_t retVal = 3; // 2 bytes for the open and closing brackets one for the '\0'
TForteUInt16 nSize = getStructSize();
retVal += (nSize > 1) ? (nSize - 1) : 0; //for the commas between the elements
retVal += (nSize * 2); //for the := of each element
const CIEC_ANY *poMembers = getMembers();
if(0 != poMembers) {
for(size_t i = 0; i < nSize; i++) {
retVal += strlen(CStringDictionary::getInstance().get(elementNames()[i])); //element name
retVal += (poMembers[i].getToStringBufferSize() - 1); //length of the element itself. -1 for the included \0 in each element
}
}
return retVal;
}
void CIEC_STRUCT::findNextNonBlankSpace(const char** paRunner) {
while(' ' == **paRunner) {
(*paRunner)++;
}
}