466 lines
12 KiB
C++
466 lines
12 KiB
C++
/*************************************************************************\
|
|
* 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
|
|
*
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
#ifndef assert // allows use of epicsAssert.h
|
|
#include <assert.h>
|
|
#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<rhs.tv_sec) {
|
|
//
|
|
// wrap around
|
|
//
|
|
tv_sec = 1 + lhs.tv_sec + (ULONG_MAX - rhs.tv_sec);
|
|
}
|
|
else {
|
|
tv_sec = lhs.tv_sec - rhs.tv_sec;
|
|
}
|
|
|
|
if (lhs.tv_nsec<rhs.tv_nsec) {
|
|
//
|
|
// Borrow
|
|
//
|
|
tv_nsec = 1 + lhs.tv_nsec + (NSecPerSec - rhs.tv_nsec);
|
|
tv_sec--;
|
|
}
|
|
else {
|
|
tv_nsec = lhs.tv_nsec - rhs.tv_nsec;
|
|
}
|
|
return aitTimeStamp(tv_sec, tv_nsec);
|
|
}
|
|
|
|
inline int operator>= (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
|