/******************************************************************************* | |
* Copyright (c) 2005 - 2015 Profactor GmbH, ACIN, fortiss GmbH, | |
* 2019 TU Wien/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, Ingo Hegny, | |
* Martin Melik Merkumians, Monika Wenger | |
* - initial implementation and rework communication infrastructure | |
* Martin Melik Merkumians - added parsing for signed time literals | |
*******************************************************************************/ | |
#include "forte_time.h" | |
#include "../../arch/timerha.h" | |
#include <stdlib.h> | |
#include <ctype.h> | |
#include "forte_constants.h" | |
#ifdef FORTE_USE_64BIT_DATATYPES | |
# include "forte_lint.h" | |
#else | |
# include "forte_dint.h" | |
#endif | |
DEFINE_FIRMWARE_DATATYPE(TIME, g_nStringIdTIME) | |
int CIEC_TIME::fromString(const char *paValue) { | |
int nRetVal = -1; | |
char* pcEnd; | |
TValueType nIntVal = 0; | |
if('t' == tolower(paValue[0])) { | |
nRetVal = 1; | |
paValue++; | |
if(('i' == tolower(paValue[0])) && ('m' == tolower(paValue[1])) && ('e' == tolower(paValue[2]))) { | |
paValue += 3; | |
nRetVal += 3; | |
} | |
if('#' == *paValue) { // the string has to start with T# | |
paValue++; | |
nRetVal++; | |
TValueType nTimeSignFactor = 1; | |
if('+' == *paValue || '-' == *paValue) { | |
if('-' == *paValue) { | |
nTimeSignFactor = -1; | |
} | |
paValue++; | |
nRetVal++; | |
} | |
TValueType nTimeFactor = 1; | |
bool bEnd = false; | |
do { | |
TValueType nBuf = forte::core::util::strtol(paValue, &pcEnd, 10); | |
switch(tolower(*pcEnd)){ | |
case 'd': | |
nTimeFactor = 24 * 60 * 60 * cgForteTimeBaseUnitsPerSecond; | |
break; | |
case 'h': | |
nTimeFactor = 60 * 60 * cgForteTimeBaseUnitsPerSecond; | |
break; | |
case 'm': | |
if('s' == tolower(*(pcEnd + 1))) { | |
nTimeFactor = cgForteTimeBaseUnitsPerSecond / forte::core::constants::cMillisecondsPerSecond; | |
++pcEnd; | |
} else { | |
nTimeFactor = 60 * cgForteTimeBaseUnitsPerSecond; | |
} | |
break; | |
case 'n': | |
if('s' == tolower(*(pcEnd + 1))) { | |
nTimeFactor = cgForteTimeBaseUnitsPerSecond / forte::core::constants::cNanosecondsPerSecond; | |
} else { | |
bEnd = true; | |
} | |
break; | |
case 's': | |
nTimeFactor = cgForteTimeBaseUnitsPerSecond; | |
break; | |
case 'u': | |
if('s' == tolower(*(pcEnd + 1))) { | |
nTimeFactor = cgForteTimeBaseUnitsPerSecond / forte::core::constants::cMicrosecondsPerSecond; | |
} else { | |
bEnd = true; | |
} | |
break; | |
case '_': | |
//ignore leading underscores | |
break; | |
default: | |
if(paValue == pcEnd) { | |
//we couldn't parse anything | |
return -1; | |
} | |
bEnd = true; | |
break; | |
} | |
nRetVal += static_cast<int>(pcEnd - paValue); | |
if(!bEnd) { | |
++nRetVal; | |
} | |
paValue = pcEnd + 1; | |
nIntVal += (nBuf * nTimeFactor * nTimeSignFactor); | |
} while(('\0' != *paValue) && (!bEnd)); | |
} else { | |
return -1; | |
} | |
} else { | |
nIntVal = forte::core::util::strtol(paValue, &pcEnd, 10); | |
nRetVal = static_cast<int>(pcEnd - paValue); | |
} | |
*this = nIntVal; | |
return nRetVal; | |
} | |
int CIEC_TIME::toString(char* paValue, size_t paBufferSize) const { | |
int nRetVal = -1; | |
if(paBufferSize > 4) { | |
#ifdef FORTE_USE_64BIT_DATATYPES | |
CIEC_LINT timeVal(getInMilliSeconds()); | |
#else //FORTE_USE_64BIT_DATATYPES | |
CIEC_DINT timeVal(getInMilliSeconds()); | |
#endif //FORTE_USE_64BIT_DATATYPES | |
nRetVal = timeVal.toString(paValue + 2, paBufferSize - 4); | |
if(-1 != nRetVal) { | |
paValue[0] = 'T'; | |
paValue[1] = '#'; | |
nRetVal += 2; | |
timeVal = getInMicroSeconds(); | |
timeVal = timeVal % 1000; //we only want the microseconds | |
if(0 != timeVal) { | |
//If we have a microsecond value add it to the literal | |
paValue[nRetVal] = '.'; | |
++nRetVal; | |
if(timeVal < 100) { | |
paValue[nRetVal] = '0'; | |
++nRetVal; | |
if(timeVal < 10) { | |
paValue[nRetVal] = '0'; | |
++nRetVal; | |
} | |
} | |
int size = timeVal.toString(paValue + nRetVal, paBufferSize - nRetVal); | |
if(-1 == size) { | |
return size; | |
} | |
nRetVal += size; | |
} | |
paValue[nRetVal] = 'm'; | |
paValue[nRetVal + 1] = 's'; | |
paValue[nRetVal + 2] = '\0'; | |
nRetVal += 2; | |
} | |
} | |
return nRetVal; | |
} | |
CIEC_TIME::TValueType CIEC_TIME::getInSeconds() const { | |
return static_cast<TValueType>(*this) / static_cast<TValueType>(cgForteTimeBaseUnitsPerSecond); | |
} | |
CIEC_TIME::TValueType CIEC_TIME::getInMilliSeconds() const { | |
return | |
(forte::core::constants::cMillisecondsPerSecond < cgForteTimeBaseUnitsPerSecond) ? | |
static_cast<TValueType>(*this) / (static_cast<TValueType>(cgForteTimeBaseUnitsPerSecond) / forte::core::constants::cMillisecondsPerSecond) : | |
static_cast<TValueType>(*this) * (forte::core::constants::cMillisecondsPerSecond / cgForteTimeBaseUnitsPerSecond); | |
} | |
CIEC_TIME::TValueType CIEC_TIME::getInMicroSeconds() const { | |
return | |
(forte::core::constants::cMicrosecondsPerSecond < cgForteTimeBaseUnitsPerSecond) ? | |
static_cast<TValueType>(*this) / (static_cast<TValueType>(cgForteTimeBaseUnitsPerSecond) / forte::core::constants::cMicrosecondsPerSecond) : | |
static_cast<TValueType>(*this) * (forte::core::constants::cMicrosecondsPerSecond / cgForteTimeBaseUnitsPerSecond); | |
} | |
CIEC_TIME::TValueType CIEC_TIME::getInNanoSeconds() const { | |
return | |
(forte::core::constants::cNanosecondsPerSecond < cgForteTimeBaseUnitsPerSecond) ? | |
static_cast<TValueType>(*this) / (static_cast<TValueType>(cgForteTimeBaseUnitsPerSecond) / forte::core::constants::cNanosecondsPerSecond) : | |
static_cast<TValueType>(*this) * (forte::core::constants::cNanosecondsPerSecond / cgForteTimeBaseUnitsPerSecond); | |
} | |
void CIEC_TIME::setFromSeconds(TValueType paValue) { | |
*this = paValue * cgForteTimeBaseUnitsPerSecond; | |
} | |
void CIEC_TIME::setFromMilliSeconds(TValueType paValue) { | |
*this = | |
(forte::core::constants::cMillisecondsPerSecond < cgForteTimeBaseUnitsPerSecond) ? | |
paValue * (cgForteTimeBaseUnitsPerSecond / forte::core::constants::cMillisecondsPerSecond) : | |
paValue / (forte::core::constants::cMillisecondsPerSecond / cgForteTimeBaseUnitsPerSecond); | |
} | |
void CIEC_TIME::setFromMicroSeconds(TValueType paValue) { | |
*this = | |
(forte::core::constants::cMicrosecondsPerSecond < cgForteTimeBaseUnitsPerSecond) ? | |
paValue * (cgForteTimeBaseUnitsPerSecond / forte::core::constants::cMicrosecondsPerSecond) : | |
paValue / (forte::core::constants::cMicrosecondsPerSecond / cgForteTimeBaseUnitsPerSecond); | |
} | |
void CIEC_TIME::setFromNanoSeconds(TValueType paValue) { | |
*this = | |
(forte::core::constants::cNanosecondsPerSecond < cgForteTimeBaseUnitsPerSecond) ? | |
paValue * (cgForteTimeBaseUnitsPerSecond / forte::core::constants::cNanosecondsPerSecond) : | |
paValue / (forte::core::constants::cNanosecondsPerSecond / cgForteTimeBaseUnitsPerSecond); | |
} |