/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ #ifndef aitHelpersInclude #define aitHelpersInclude /* * Authors: Jeff Hill and Jim Kowalkowski * Date: 6/20/96 * * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd * */ #include #include #ifndef assert // allows use of epicsAssert.h #include #endif #include "shareLib.h" #define NSecPerSec 1000000000u #define NSecPerUSec 1000u #define SecPerMin 60u inline char* strDup(const char* x) { char* y = new char[strlen(x)+1]; strcpy(y,x); return y; } struct timespec; struct epicsTimeStamp; class epicsTime; class gdd; class epicsShareClass aitTimeStamp { friend inline aitTimeStamp operator+ (const aitTimeStamp &lhs, const aitTimeStamp &rhs); friend inline aitTimeStamp operator- (const aitTimeStamp &lhs, const aitTimeStamp &rhs); friend inline int operator>= (const aitTimeStamp &lhs, const aitTimeStamp &rhs); friend class gdd; public: aitTimeStamp () : tv_sec(0u), tv_nsec(0u) {} aitTimeStamp (const aitTimeStamp &t) : tv_sec(t.tv_sec), tv_nsec(t.tv_nsec) {} aitTimeStamp (const unsigned long tv_secIn, const unsigned long tv_nsecIn) : tv_sec(tv_secIn), tv_nsec(tv_nsecIn) { if (tv_nsecIn>=NSecPerSec) { this->tv_sec += this->tv_nsec/NSecPerSec; this->tv_nsec = this->tv_nsec%NSecPerSec; } } // // fetched as fields so this file is not required // to include os dependent struct timeval // void getTV(long &tv_secOut, long &uSecOut) const { assert (this->tv_sec<=LONG_MAX); tv_secOut = (long) this->tv_sec; assert (this->tv_nsec<=LONG_MAX); uSecOut = (long) this->tv_nsec/NSecPerUSec; } // // for use when loading struct timeval // void get(unsigned long &tv_secOut, unsigned long &tv_nsecOut) const { tv_secOut = this->tv_sec; tv_nsecOut = this->tv_nsec; } operator double() const { return ((double)this->tv_nsec)/NSecPerSec+this->tv_sec; } operator float() const { return ((float)this->tv_nsec)/NSecPerSec+this->tv_sec; } // // convert to and from POSIX timespec format // operator struct timespec () const; void get (struct timespec &) const; aitTimeStamp (const struct timespec &ts); aitTimeStamp operator = (const struct timespec &rhs); // // convert to and from EPICS epicsTimeStamp format // operator struct epicsTimeStamp () const; void get (struct epicsTimeStamp &) const; aitTimeStamp (const epicsTimeStamp &ts); aitTimeStamp operator = (const epicsTimeStamp &rhs); // conversion to from epicsTime aitTimeStamp (const epicsTime &ts); aitTimeStamp operator = (const epicsTime &rhs); operator epicsTime () const; static aitTimeStamp getCurrent(); //private: unsigned long tv_sec; unsigned long tv_nsec; private: static const unsigned epicsEpochSecPast1970; }; inline aitTimeStamp operator+ (const aitTimeStamp &lhs, const aitTimeStamp &rhs) { return aitTimeStamp(lhs.tv_sec + rhs.tv_sec, lhs.tv_nsec + rhs.tv_nsec); } // // like data type unsigned this assumes that the lhs > rhs // (otherwise we assume tv_sec wrap around) // inline aitTimeStamp operator- (const aitTimeStamp &lhs, const aitTimeStamp &rhs) { unsigned long tv_nsec, tv_sec; if (lhs.tv_sec= (const aitTimeStamp &lhs, const aitTimeStamp &rhs) { int rc=0; if (lhs.tv_sec>rhs.tv_sec) rc=1; else if(lhs.tv_sec==rhs.tv_sec) if(lhs.tv_nsec>=rhs.tv_nsec) rc=1; return rc; } // --------------------------------------------------------------------------- // very simple class for string storage (for now) // // enum aitStrType { aitStrRefConstImortal, // any constant string that always exists - ie "abc" aitStrRefConst, // user provides constant string buffer for life of aitSting aitStrRef, // user provides modifiable string buffer for life of aitSting aitStrCopy}; // aitSting copies into internal storage class epicsShareClass aitString { public: inline aitString(void); inline aitString(const aitString* p); inline aitString(const aitString& p); inline aitString(const char* p, aitStrType type=aitStrCopy); inline aitString(const char* p, aitStrType type, unsigned strLength); inline aitString(const char* p, aitStrType type, unsigned strLength, unsigned bufSize); inline ~aitString(void); // free up string is required inline void clear(void); // clear everything, free string if required void dump(void) const; void dump(const char* id) const; // casts from aitString to other things - pulls info out of aitString inline operator aitUint16(void) const { return (aitUint16)this->len; } inline operator aitUint32(void) const { return (aitUint32)this->len; } inline operator aitInt32(void) const { return (aitInt32)this->len; } inline operator const char*(void) const { return this->str; } inline operator char*(void) const { assert(type!=aitStrRefConst && type!=aitStrRefConstImortal); return str; } inline int isConstant(void) const; inline aitUint32 length(void) const { return (aitUint32)this->len; } inline const char* string(void) const { return this->str; } // completely reset the aitString to a new value // - the same as copy() inline aitString& operator=(const aitString& pString); inline aitString& operator=(const aitString* pString); inline aitString& operator=(const char* pString); inline int copy(const aitString* pString); inline int copy(const aitString& pString); inline int copy(const char* pString); inline int copy(const char* pString, unsigned stringLength); int copy(const char* pString, unsigned stringLength, unsigned bufSize); // // make ait string point at string in application's modifiable buffer // inline int installBuf(const char* pString); inline int installBuf(const char* pString, unsigned stringLength); inline int installBuf(const char* pString, unsigned stringLength, unsigned bufSize); // // make ait string point at constant string in application's constant buffer // inline int installConstBuf(const char* pString); inline int installConstBuf(const char* pString, unsigned stringLength); inline int installConstBuf(const char* pString, unsigned stringLength, unsigned bufSize); // // make ait string point at constant string in application's constant buffer // that exists forever (such as "abc") // inline int installConstImortalBuf(const char* pString); inline int installConstImortalBuf(const char* pString, unsigned stringLength); inline int installConstImortalBuf(const char* pString, unsigned stringLength, unsigned bufSize); inline void extractString(char* to_here, unsigned bufSize); // take the aitString array, and put it and all the string into buf, // return the total length the data copied static aitUint32 totalLength(aitString* array,aitIndex arraySize); static aitUint32 stringsLength(aitString* array,aitIndex arraySize); static aitIndex compact(aitString* array, aitIndex arraySize, void* buf, aitIndex bufSize); // // for gdd's use only! (to construct class inside union) // (it is possible to leak memory if this is called on // an already constructed aitString). This practice should // be eliminated by deriving from aitString and replacing // the new operator? // inline void init(void); private: char* str; unsigned len:14; // actual length of string unsigned bufLen:14; // length of string buffer unsigned type:4; // aitStrType goes here void mallocFailure(void); inline aitStrType getType(void) const { return (aitStrType)type; } int init(const char* p, aitStrType type, unsigned strLength, unsigned bufSize); }; inline void aitString::init(void) { this->str=(char *)""; this->len=0u; this->bufLen=1u; this->type=aitStrRefConstImortal; } inline int aitString::isConstant(void) const { return ( (getType()==aitStrRefConst||getType()==aitStrRefConstImortal) && this->str)?1:0; } inline void aitString::clear(void) { if(this->str && this->type==aitStrCopy) delete [] this->str; this->init(); } inline void aitString::extractString(char* p, unsigned bufLength) { if (bufLength==0u) { return; } else if (this->str) { strncpy(p,this->str,bufLength); p[bufLength-1u]='\0'; } else { p[0u] = '\0'; } } // // make ait string point at string in application's buffer // inline int aitString::installBuf(const char* pString, unsigned strLengthIn, unsigned bufSizeIn) { if (this->type==aitStrCopy) { delete [] this->str; } this->str = (char *) pString; this->bufLen = bufSizeIn; this->type = aitStrRef; this->len = strLengthIn; return 0; } inline int aitString::installBuf(const char* pString) { unsigned strLengthIn = strlen(pString); return this->installBuf(pString, strLengthIn, strLengthIn+1u); } inline int aitString::installBuf(const char* pString, unsigned strLengthIn) { return this->installBuf(pString, strLengthIn, strLengthIn+1u); } // // make ait string point at constant string in application's buffer // inline int aitString::installConstBuf(const char* pString, unsigned strLengthIn, unsigned bufSizeIn) { if (this->type==aitStrCopy) { delete [] this->str; } this->str = (char *) pString; this->bufLen = bufSizeIn; this->type = aitStrRefConst; this->len = strLengthIn; return 0; } inline int aitString::installConstBuf(const char* pString) { unsigned strLengthIn = strlen(pString); return this->installConstBuf(pString, strLengthIn, strLengthIn+1u); } inline int aitString::installConstBuf(const char* pString, unsigned strLengthIn) { return this->installConstBuf(pString, strLengthIn, strLengthIn+1u); } // // make ait string point at constant string in application's buffer // that always exists (such as "abc") // inline int aitString::installConstImortalBuf(const char* pString, unsigned strLengthIn, unsigned bufSizeIn) { if (this->type==aitStrCopy) { delete [] this->str; } this->str = (char *) pString; this->bufLen = bufSizeIn; this->type = aitStrRefConstImortal; this->len = strLengthIn; return 0; } inline int aitString::installConstImortalBuf(const char* pString) { unsigned strLengthIn = strlen(pString); return this->installConstImortalBuf(pString, strLengthIn, strLengthIn+1u); } inline int aitString::installConstImortalBuf(const char* pString, unsigned strLengthIn) { return this->installConstImortalBuf(pString, strLengthIn, strLengthIn+1u); } inline int aitString::copy(const char* pString, unsigned stringLength) { return this->copy(pString, stringLength, this->bufLen>(stringLength+1u) ? this->bufLen : (stringLength+1u) ); } inline int aitString::copy(const char* p) { return this->copy(p, strlen(p)); } inline int aitString::copy(const aitString* p) { if (p->type==aitStrRefConstImortal) { // // fast reference if the string is constant and it // exists forever // return this->installConstImortalBuf(p->str, p->len, p->len+1u); } return this->copy(p->str, p->len); } inline int aitString::copy(const aitString& p) { return this->copy(&p); } inline aitString& aitString::operator=(const aitString& p) { this->copy(p); return *this; } inline aitString& aitString::operator=(const aitString* p) { this->copy(p); return *this; } inline aitString& aitString::operator=(const char* p) { this->copy(p); return *this; } inline aitString::~aitString(void) { // dump("~aitString"); this->clear(); } inline aitString::aitString(void) { this->init(); } inline aitString::aitString(const char* p, aitStrType typeIn) { unsigned strLengthIn = strlen(p); this->init(p, typeIn, strLengthIn, strLengthIn+1u); } inline aitString::aitString(const char* p, aitStrType typeIn, unsigned strLengthIn) { this->init(p, typeIn, strLengthIn, strLengthIn+1u); } inline aitString::aitString(const char* p, aitStrType typeIn, unsigned strLength, unsigned bufSize) { this->init(p,typeIn,strLength,bufSize); } inline aitString::aitString(const aitString* p) { this->init(); this->copy(p); } inline aitString::aitString(const aitString& p) { this->init(); this->copy(p); } #endif // aitHelpersInclude