converted by lore's source converter
//////////////////////////////////////////////////////////////////////////////
//
// MTypes.cpp: Implementation of the basic type classes
//
//////////////////////////////////////////////////////////////////////////////
//
// author: Eckhard Kantz
// website: http://wegalink.eu
//
//////////////////////////////////////////////////////////////////////////////
/*
This is FREE software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following conditions:
There are no conditions imposed on the use of this software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "MTypes.h"
//////////////////////////////////////////////////////////////////////
// MString Class
//////////////////////////////////////////////////////////////////////
MString::MString()
{
//Reset text array and length
pText = NULL;
uLength = 0;
}
MString::MString(const int8* _text)
{
//Initialize text array
pText = NULL;
setText(_text);
}
MString::MString(const MString & _String)
{
//Initialize text array
pText = NULL;
setText(_String.getText());
}
MString::MString(uint32 _uLength)
{
//Generate empty text array
uLength = _uLength;
pText = new int8[uLength + 1];
memset(pText,0,uLength+1);
}
MString::~MString()
{
//Remove text array from heap
delete[] pText;
}
const int8* MString::getText() const
{
//Return text array or empty string
if(NULL != pText){
return pText;
}else{
return (int8*)"";
}
}
int8* MString::getBuffer() const
{
// Check length and return text array
if (uLength>0){
return pText;
}else{
return "";
}
}
uint32 MString::getLength() const
{
//Return text length
return uLength;
}
int8* MString::setText(const int8* _pText)
{
//Replace existing text array with a new string
uLength = (uint32)strlen(_pText);
delete[] pText;
pText = new int8[uLength+1];
if (uLength>0){
memcpy(pText,_pText,uLength);
}
pText[uLength] = 0;
return pText;
}
void MString::setText(const MString & _String)
{
//Replace existing text array with the content of a given MString object
setText(_String.getText());
}
int8* MString::setText(const int8* pFirst, const int8* pLast)
{
//Replace existing text array with a given substring
if (pFirst<=pLast){
uLength = (uint32)(pLast-pFirst+1);
}else{
uLength = 0;
}
delete[] pText;
pText = new int8[uLength+1];
if (uLength>0){
memcpy(pText, pFirst, uLength);
}
pText[uLength] = 0;
return pText;
}
void MString::setLength(uint32 _uLength)
{
//Reallocate the text array with a new size
uLength = _uLength;
delete[] pText;
pText = new int8[uLength+1];
*(pText+uLength) = 0;
}
void MString::setAt(uint32 _uPos, uint32 _uChar)
{
//Replace a single character in the text array
if(_uPos < uLength){
pText[_uPos] = (int8)_uChar;
}
}
uint32 MString::operator[](uint32 _uPos) const
{
//Return single character at a given position in the text array
if(_uPos >= uLength){
return 0;
}else{
return pText[_uPos];
}
}
void MString::operator += (MString& mString)
{
operator += (mString.getBuffer());
}
void MString::operator += (int8* pString)
{
//Preserve existing text array
int8* pOldText = pText;
uint32 uOldLength = uLength;
//Add existing and new string into the new text array
uint32 uStringLength = (uint32)strlen(pString);
uLength += uStringLength;
pText = new int8[uLength+1];
pText[uLength]=0;
if (uOldLength>0){
memcpy(pText,pOldText,uOldLength);
}
if (uLength>uOldLength){
memcpy(pText+uOldLength,pString,uStringLength);
}
delete[] pOldText;
}
void MString::operator += (uint32 uNum)
{
MString mString;
mString = uNum;
operator += (mString.getBuffer());
}
void MString::operator += (uint64 u64Num)
{
MString mString;
mString = u64Num;
operator += (mString.getBuffer());
}
void MString::operator = (const MString& _mString)
{
//Take over content from a given MString object
setText(_mString.getText());
}
void MString::operator = (const int8* szString)
{
//Take over content from a given MString object
setText(szString);
}
void MString::operator=(const uint32 uNum)
{
char achNum[20];
sprintf(achNum,"%u",uNum);
setText(achNum);
}
void MString::operator=(const uint64 u64Num)
{
#define NUM_BILLION 1000000000
char achNum[40];
if (u64Num/NUM_BILLION >= NUM_BILLION){
sprintf(achNum,"%u%u%u",
(uint32)((u64Num/NUM_BILLION)/NUM_BILLION),
(uint32)((u64Num/NUM_BILLION)%NUM_BILLION),
(uint32)(u64Num%NUM_BILLION));
}else if(u64Num >= NUM_BILLION){
sprintf(achNum,"%u%u",
(uint32)(u64Num/NUM_BILLION),
(uint32)(u64Num%NUM_BILLION));
}else{
sprintf(achNum,"%u",(uint32)u64Num);
}
setText(achNum);
}
bool MString::operator==(const MString& mTxt)
{
//Compare the text content of two MString objects
if (mTxt.getLength()!=uLength){
return false;
}else{
if (0==strcmp(mTxt.getBuffer(),pText)){
return true;
}else{
return false;
}
}
}
bool MString::operator==(int8* achTxt)
{
//Compare the text array with a given string
if (strlen(achTxt)!=uLength){
return false;
}else{
if (0==strcmp(achTxt,pText)){
return true;
}else{
return false;
}
}
}
bool MString::operator!=(const MString& mTxt)
{
//Compare the text content of two MString objects
if (mTxt.getLength()!=uLength){
return true;
}else{
if (0!=strcmp(mTxt.getBuffer(),pText)){
return true;
}else{
return false;
}
}
}
bool MString::operator!=(int8* achTxt)
{
//Compare the text array with a given string
if (strlen(achTxt)!=uLength){
return true;
}else{
if (0!=strcmp(achTxt,pText)){
return true;
}else{
return false;
}
}
}
int MString::compareHeader(const int8* _header)
{
//Compare the first characters in the text array with a given header string
return strncmp(pText, _header, strlen(_header));
}
unsigned int MString::Match(MLString** ppLMatch, int8 const* pPattern)
{
int8* pFirst = pText; //first matching character
int8* pSrcText = pText; //current text position
int8 chMatch = ' '; //single character to be found
int8* szMatch = NULL; //group of alternative characters
uint32 nSkip; //skip any character
uint32 nMatch; //current match number
uint32 nMatchMin; //minimal match number
uint32 nMatchMax; //maximal match number
uint32 nLMatch = 0; //number of valid result list members
for(;;){
//Evaluate next pattern element
nSkip = 0;
szMatch = NULL;
switch(*pPattern){
case 0:
return nLMatch;
case '(':
pFirst = pSrcText;
pPattern++;
continue;
case ')':
if(NULL == *ppLMatch){
*ppLMatch = new MLString;
}
(*ppLMatch)->setText(pFirst, pSrcText-1);
ppLMatch = (*ppLMatch)->getAdrNext();
nLMatch++;
pPattern++;
continue;
case '.':
pPattern++;
//Determine modifiers
switch(*pPattern){
case'*':
nSkip = MAX_UINT32;
pPattern++;
break;
case '+':
nSkip = MAX_UINT32;
pSrcText++;
pPattern++;
default:
nSkip = 1;
break;
}
break;
case '\\':
pPattern++;
switch(*pPattern){
case 's': //white spaces
szMatch = " \t\r\n";
break;
case 'd': //digits
szMatch = "0123456789";
break;
case 'w': //word characters
szMatch = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
break;
default:
chMatch = *pPattern;
break;
}
pPattern++;
break;
default:
chMatch = *pPattern++;
break;
}
//Determine possible modifiers
switch(*pPattern){
case '*':
nMatchMin = 0;
nMatchMax = MAX_UINT32;
pPattern++;
break;
case '+':
nMatchMin = 1;
nMatchMax = MAX_UINT32;
pPattern++;
break;
case '?':
nMatchMin = 0;
nMatchMax = 1;
pPattern++;
break;
default:
nMatchMin = 1;
nMatchMax = 1;
break;
}
//Step over matching character(s)
for(nMatch=0;;){
if(NULL == szMatch){
while(nMatch < nMatchMax && chMatch == *pSrcText){
nMatch++;
pSrcText++;
}
}else{
while(nMatch < nMatchMax && NULL != strchr(szMatch, (int32)*pSrcText)){
nMatch++;
pSrcText++;
}
}
if(nMatch < nMatchMin){
if(nSkip > nMatch){
nSkip -= nMatch + 1;
pSrcText++;
nMatch = 0;
continue;
}
return nLMatch;
}
break;
}
}
}
// Conversion function
uint32 MString::getNum()
{
uint32 uNum = 0;
for (uint32 i=0;i<getLength();i++){
uNum *= 10;
uNum += *(pText+i)-'0';
}
return uNum;
}
//Backup and restore
const int8* MString::read(const int8* pFilename)
{
FILE* pFile;
struct stat buf;
int32 fh;
uint32 uFileSize = 0;
//Determine file size
if (-1!=(fh = open(pFilename,O_RDONLY))){
if (0==fstat(fh,&buf)){
uFileSize = buf.st_size;
}else{
throw MException("File status not accessible.");
}
close( fh );
}else{
throw MException("Data file not found.");
}
pFile = fopen(pFilename,"rb");
if(NULL==pFile){
throw MException("Data file can not be opened.");
}else{
try{
setLength(uFileSize);
fread(pText,1,uFileSize,pFile);
fclose(pFile);
}catch(...){
fclose(pFile);
throw MException("Data file not readable.");
}
}
return pText;
}
void MString::write(const int8* pFilename)
{
FILE* pFile;
if (NULL!=(pFile = fopen(pFilename,"wb"))){
fwrite(pText,uLength,1,pFile);
}
fclose(pFile);
}
//////////////////////////////////////////////////////////////////////
// MLString Class
//////////////////////////////////////////////////////////////////////
MLString::MLString()
{
pNext = NULL;
}
MLString::~MLString()
{
}
MLString* MLString::getNext()
{
return pNext;
}
MString* MLString::setNext(MLString* _Next)
{
return(pNext = _Next);
}
MLString** MLString::getAdrNext()
{
return &pNext;
}
//////////////////////////////////////////////////////////////////////
// MMString Class
//////////////////////////////////////////////////////////////////////
MMString::MMString(const MString& _mSourceString,const int8* _pszDelimiters)
:mSourceString(_mSourceString)
{
uCurrentPosition = 0;
mSetOfDelimiters.setText(_pszDelimiters);
}
MMString::~MMString()
{
}
int8* MMString::getNextDelimitedString()
{
uint32 uSubStringLength = 0;
bool fDelimiterFound = false;
//Current position must not be greater than the string length
if(uCurrentPosition >= mSourceString.uLength){
return NULL;
}
for(;uCurrentPosition<mSourceString.uLength;uCurrentPosition++){
for(uint32 k=0;k<mSetOfDelimiters.getLength();k++){
if((uint32)*(mSourceString.getText()+uCurrentPosition) == mSetOfDelimiters[k]){
fDelimiterFound = true;
break;
}
}
if(true==fDelimiterFound){
if(uSubStringLength>0){
break;
}
fDelimiterFound = false;
}else{
uSubStringLength++;
}
}
//Transfer substring
setLength(uSubStringLength);
for(uint32 m=0;m<uSubStringLength;m++){
setAt(m, (uint32)*(mSourceString.getText()+uCurrentPosition-uSubStringLength+m));
}
return pText;
}
void MMString::operator=(const MMString&)
{
}
int8* MMString::setDelimiters(int8* pszDelimiters)
{
return mSetOfDelimiters.setText(pszDelimiters);
}
void MMString::resetPosition()
{
uCurrentPosition = 0;
}
//////////////////////////////////////////////////////////////////////
// MDateTime class
//////////////////////////////////////////////////////////////////////
MDateTime::MDateTime()
{
}
MDateTime::~MDateTime()
{
}
// Systime access function (nanoseconds)
int64 MDateTime::getSysClockNanoSec()
{
#ifndef WIN32
struct timeval stTimeValue;
struct timezone stTimeZone;
gettimeofday(&stTimeValue,&stTimeZone);
return (((int64)1000000000*stTimeValue.tv_sec)+(int64)1000*stTimeValue.tv_usec);
#else
struct timeb timebuffer;
ftime( &timebuffer );
return (int64)1000000*((int64)1000*timebuffer.time+timebuffer.millitm);
#endif
}
// Time conversion
uint64 MDateTime::getNanoSec(const char* szDateTime)
{
#define TIMEZONE 60*60
MString mDateTime(szDateTime);
MMString mNum(mDateTime," -:.cdehilmnostu");
// Date/time components
time_t nTime;
int32 nMilliSeconds;
struct tm stDateTime;
stDateTime.tm_isdst = 0;
// Year
mNum.resetPosition();
if (NULL==mNum.getNextDelimitedString()){
throw MException("Invalid year");
}
stDateTime.tm_year = mNum.getNum() - 1900;
// Month
if (NULL==mNum.getNextDelimitedString()){
throw MException("Invalid month");
}
stDateTime.tm_mon = mNum.getNum() - 1;
// Day
if (NULL==mNum.getNextDelimitedString()){
throw MException("Invalid day");
}
stDateTime.tm_mday = mNum.getNum();
// Hour
if (NULL==mNum.getNextDelimitedString()){
throw MException("Invalid hour");
}
stDateTime.tm_hour = mNum.getNum();
// Minute
if (NULL==mNum.getNextDelimitedString()){
throw MException("Invalid minute");
}
stDateTime.tm_min = mNum.getNum();
// Second
if (NULL==mNum.getNextDelimitedString()){
throw MException("Invalid second");
}
stDateTime.tm_sec = mNum.getNum();
// Millisecond
if (NULL==mNum.getNextDelimitedString()){
nMilliSeconds = 0;
}else{
nMilliSeconds = mNum.getNum();
}
// Convert
if (-1==(nTime=mktime(&stDateTime))){
throw MException("Time not recognized",szDateTime);
}
return (((uint64)(nTime + TIMEZONE) * 1000) + nMilliSeconds) * 1000000;
}
MString MDateTime::getTimeUTC(uint32 uDateTime)
{
if (0==uDateTime){
uDateTime = time(NULL);
}
struct tm* pDateTime = gmtime((time_t*)&uDateTime);
char achUTC[20];
sprintf(achUTC,"%4u-%02u-%02u %02u:%02u:%02u",
pDateTime->tm_year + 1900,
pDateTime->tm_mon + 1,
pDateTime->tm_mday,
pDateTime->tm_hour,
pDateTime->tm_min,
pDateTime->tm_sec);
return MString(achUTC);
}
//////////////////////////////////////////////////////////////////////
// MBenchmark class
//////////////////////////////////////////////////////////////////////
#define TOLERANCE 150
#define PRECISION 10L
#define RANGE_MILLI 1000000L
#define RANGE_MICRO 1000L
#define RANGE_MIN 100L
#define RANGE_MAX 1000000L
MBenchmark::MBenchmark(int32 _nLoops, int32 _nTrialPeriodMilliSec, int32 _nTrials)
{
nLoops = _nLoops > 0 ? _nLoops : 1;
nTrials = _nTrials > 0 ? _nTrials : 1;
n64TrialPeriod = _nTrialPeriodMilliSec > 0 ? _nTrialPeriodMilliSec : 0;
n64TrialPeriod *= 1000000; //convert to nanoseconds
// Set start condition
nCurLoop = 0;
nCurTrial = 0;
}
MBenchmark::~MBenchmark()
{
}
bool MBenchmark::run()
{
// Check loop status
if(--nCurLoop > 0){
return true;
}
// Check for start condition
if(0==nCurTrial){
// Initiate new run
nCycles = 1;
nCurLoop = nLoops;
nCurTrial = nTrials;
n64DurationMin = MAX_INT64;
n64ZeroOffsetMin = MAX_INT64;
n64TrialEnd = mDateTime.getSysClockNanoSec() + n64TrialPeriod;
return true;
}
// Check for trial end
if(n64TrialEnd > (n64CurTime = mDateTime.getSysClockNanoSec())){
nCycles++;
nCurLoop = nLoops;
return true;
}else{
// Evaluate trial results
if(nCycles * nLoops != 0){
n64Duration = (n64TrialPeriod + n64CurTime - n64TrialEnd)* PRECISION / (nCycles * nLoops);
// Evaluate empty loop (zero offset)
nCurLoop = nLoops;
nCurCycle = nCycles;
n64CurTime = mDateTime.getSysClockNanoSec();
while(dummy());
n64TrialEnd = mDateTime.getSysClockNanoSec();
n64ZeroOffset = (n64TrialEnd - n64CurTime)* PRECISION / (nCycles * nLoops);
}else{
n64Duration = -1;
}
if(n64Duration > 0 && n64Duration < n64DurationMin){
n64DurationMin = n64Duration;
}
if(n64ZeroOffset >= 0 && n64ZeroOffset < n64ZeroOffsetMin){
n64ZeroOffsetMin = n64ZeroOffset;
}
if(--nCurTrial > 0){
nCycles = 1;
nCurLoop = nLoops;
n64DurationMin = MAX_INT64;
n64ZeroOffsetMin = MAX_INT64;
n64TrialEnd = mDateTime.getSysClockNanoSec() + n64TrialPeriod;
return true;
}
return false;
}
}
bool MBenchmark::dummy()
{
if(nCurLoop-- > 0){
return true;
}
if(nCurCycle-- > 0){
nCurLoop = nLoops;
return true;
}
return false;
}
MString MBenchmark::info(int64 n64Reference,int64 n64Divisor)
{
int8 achInfo[1000];
int8 achFlag[1000];
if(n64Divisor > 1){
n64DurationMin = (n64DurationMin -n64ZeroOffsetMin) /n64Divisor;
}else{
n64DurationMin = n64DurationMin -n64ZeroOffsetMin;
}
if((int32)n64DurationMin < (int32)n64Reference){
sprintf(achFlag,"--");
}else if(100*(int32)n64DurationMin > TOLERANCE*(int32)n64Reference){
sprintf(achFlag,"++");
}else{
sprintf(achFlag," ");
}
if((int32)n64DurationMin <= 0){
// Invalid
sprintf(achInfo," n.a. ");
}else if((int32)(n64DurationMin/(PRECISION*RANGE_MILLI)) > RANGE_MAX){
// Range exceeded
sprintf(achInfo," - out of range -");
}else if((int32)(n64DurationMin/(PRECISION*RANGE_MILLI)) >= RANGE_MIN &&
(int32)(n64DurationMin/RANGE_MILLI) >= 0){
// Millisecond range
sprintf(achInfo,"%6u ms ref:%6u %s",
(int32)(n64DurationMin/(PRECISION*RANGE_MILLI)),
(int32)(n64Reference/(PRECISION*RANGE_MILLI)),
achFlag);
}else if((int32)(n64DurationMin/(PRECISION*RANGE_MICRO)) >= RANGE_MIN &&
(int32)(n64DurationMin/(RANGE_MICRO*RANGE_MIN)) >= 0){
// Microsecond range
sprintf(achInfo,"%6u us ref:%6u %s",
(int32)(n64DurationMin/(PRECISION*RANGE_MICRO)),
(int32)(n64Reference/(PRECISION*RANGE_MICRO)),
achFlag);
}else if((int32)(n64DurationMin/PRECISION) >= RANGE_MIN){
// Nanosecond range
sprintf(achInfo,"%6u ns ref:%6u %s",
(int32)(n64DurationMin/PRECISION),
(int32)(n64Reference/PRECISION),
achFlag);
}else{
// Sub-nanosecond range
sprintf(achInfo,"%6.1f ns ref:%6.1f %s",(float)n64DurationMin/PRECISION,(float)n64Reference/PRECISION,achFlag);
}
return MString(achInfo);
}
//////////////////////////////////////////////////////////////////////
// MException Class
//////////////////////////////////////////////////////////////////////
MException::MException()
{
pData = NULL;
putMessage("General exception encountered");
putContext("");
}
MException::MException(void* _pData)
{
pData = _pData;
putMessage("Exception with data encountered");
putContext("");
}
MException::MException(MString& mMessage)
{
pData = NULL;
putMessage(mMessage.getText());
putContext("");
}
MException::MException(const int8* _pMessage)
{
pData = NULL;
putMessage(_pMessage);
putContext("");
}
MException::MException(MString& mMessage,int32 _nParameter)
{
pData = NULL;
putMessage(mMessage.getText());
MString mParameter(_nParameter);
putContext(mParameter.getText());
}
MException::MException(const int8* _pMessage,int32 _nParameter)
{
pData = NULL;
putMessage(_pMessage);
MString mParameter(_nParameter);
putContext(mParameter.getText());
}
MException::MException(MString& mMessage,MString& mContext)
{
pData = NULL;
putMessage(mMessage.getText());
putContext(mContext.getText());
}
MException::MException(const int8* _pMessage,MString& mContext)
{
pData = NULL;
putMessage(_pMessage);
putContext(mContext.getText());
}
MException::MException(const int8* _pMessage,const int8* _pContext)
{
pData = NULL;
putMessage(_pMessage);
putContext(_pContext);
}
MException::MException(void* _pData,MString& mMessage)
{
pData = _pData;
putMessage(mMessage.getText());
putContext("");
}
MException::MException(void* _pData,const int8* _pMessage)
{
pData = _pData;
putMessage(_pMessage);
putContext("");
}
MException::MException(void* _pData,MString& mMessage,MString& mContext)
{
pData = _pData;
putMessage(mMessage.getText());
putContext(mContext.getText());
}
MException::MException(void* _pData,const int8* _pMessage,MString& mContext)
{
pData = _pData;
putMessage(_pMessage);
putContext(mContext.getText());
}
MException::MException(void* _pData,const int8* _pMessage,const int8* _pContext)
{
pData = _pData;
putMessage(_pMessage);
putContext(_pContext);
}
MException::MException( const MException &E)
{
pData = E.pData;
putMessage(E.pMessage);
putContext(E.pContext);
}
MException::~MException()
{
delete pMessage;
delete pContext;
}
void MException::putMessage(const int8* _pMessage)
{
pMessage = new int8[strlen(_pMessage)+1];
strcpy(pMessage,_pMessage);
}
void MException::putContext(const int8* _pContext)
{
pContext = new int8[strlen(_pContext)+1];
strcpy(pContext,_pContext);
}
void* MException::getData()
{
return pData;
}
int8* MException::getMessage()
{
return pMessage;
}
int8* MException::getContext()
{
return pContext;
}