general indent beautification

This commit is contained in:
Matej Sekoranja
2016-03-10 23:36:16 +01:00
parent d139c42d17
commit 5279d247ca
110 changed files with 21778 additions and 21525 deletions
+35 -34
View File
@@ -37,7 +37,7 @@ const std::string &Properties::getProperty(const string &key) const
return propertiesIterator->second;
} else {
THROW_BASE_EXCEPTION(string("Property not found in the map: ") + key);
}
}
}
const std::string &Properties::getProperty(const string &key, const string &defaultValue) const
@@ -125,7 +125,7 @@ void Properties::store(const std::string& fname) const
void Properties::store(std::ostream& strm) const
{
for(_properties_t::const_iterator it=_properties.begin(), end=_properties.end();
it!=end && strm.good(); ++it)
it!=end && strm.good(); ++it)
{
strm << it->first << " = " << it->second << "\n";
}
@@ -133,12 +133,12 @@ void Properties::store(std::ostream& strm) const
void Properties::list()
{
for (std::map<std::string,std::string>::iterator propertiesIterator = _properties.begin() ;
propertiesIterator != _properties.end();
propertiesIterator++ )
{
cout << "Key:" << propertiesIterator->first << ",Value: " << propertiesIterator->second << endl;
}
for (std::map<std::string,std::string>::iterator propertiesIterator = _properties.begin() ;
propertiesIterator != _properties.end();
propertiesIterator++ )
{
cout << "Key:" << propertiesIterator->first << ",Value: " << propertiesIterator->second << endl;
}
}
bool Configuration::getPropertyAsBoolean(const std::string &name, const bool defaultValue) const
@@ -160,18 +160,18 @@ bool Configuration::getPropertyAsBoolean(const std::string &name, const bool def
epics::pvData::int32 Configuration::getPropertyAsInteger(const std::string &name, const epics::pvData::int32 defaultValue) const
{
try{
try {
return castUnsafe<epics::pvData::int32>(getPropertyAsString(name, ""));
}catch(std::runtime_error&){
} catch(std::runtime_error&) {
return defaultValue;
}
}
float Configuration::getPropertyAsFloat(const std::string &name, const float defaultValue) const
{
try{
try {
return castUnsafe<float>(getPropertyAsString(name, ""));
}catch(std::runtime_error&){
} catch(std::runtime_error&) {
return defaultValue;
}
}
@@ -180,7 +180,7 @@ double Configuration::getPropertyAsDouble(const std::string &name, const double
{
try {
return castUnsafe<double>(getPropertyAsString(name, ""));
}catch(std::runtime_error&){
} catch(std::runtime_error&) {
return defaultValue;
}
}
@@ -238,7 +238,7 @@ bool ConfigurationEnviron::tryGetPropertyAsString(const std::string& name, std::
bool ConfigurationStack::tryGetPropertyAsString(const std::string& name, std::string* val) const
{
for(confs_t::const_reverse_iterator it = confs.rbegin(), end = confs.rend();
it!=end; ++it)
it!=end; ++it)
{
Configuration& conf = **it;
if(conf.tryGetPropertyAsString(name, val))
@@ -295,24 +295,24 @@ Configuration::shared_pointer ConfigurationBuilder::build()
void ConfigurationProviderImpl::registerConfiguration(const string &name, Configuration::shared_pointer const & configuration)
{
Lock guard(_mutex);
std::map<std::string,Configuration::shared_pointer>::iterator configsIter = _configs.find(name);
if(configsIter != _configs.end())
{
string msg = "configuration with name " + name + " already registered";
THROW_BASE_EXCEPTION(msg.c_str());
}
_configs[name] = configuration;
Lock guard(_mutex);
std::map<std::string,Configuration::shared_pointer>::iterator configsIter = _configs.find(name);
if(configsIter != _configs.end())
{
string msg = "configuration with name " + name + " already registered";
THROW_BASE_EXCEPTION(msg.c_str());
}
_configs[name] = configuration;
}
Configuration::shared_pointer ConfigurationProviderImpl::getConfiguration(const string &name)
{
Lock guard(_mutex);
std::map<std::string,Configuration::shared_pointer>::iterator configsIter = _configs.find(name);
if(configsIter != _configs.end())
{
return configsIter->second;
}
if(configsIter != _configs.end())
{
return configsIter->second;
}
Configuration::shared_pointer env(new ConfigurationEnviron); // default to environment only
_configs[name] = env; // ensure that a later attempt to define this config will fail
return env;
@@ -323,15 +323,16 @@ Mutex conf_factory_mutex;
ConfigurationProvider::shared_pointer ConfigurationFactory::getProvider()
{
Lock guard(conf_factory_mutex);
if(configurationProvider.get() == NULL)
{
configurationProvider.reset(new ConfigurationProviderImpl());
Lock guard(conf_factory_mutex);
if(configurationProvider.get() == NULL)
{
configurationProvider.reset(new ConfigurationProviderImpl());
Configuration::shared_pointer systemConfig(new ConfigurationEnviron);
configurationProvider->registerConfiguration("system", systemConfig);
}
return configurationProvider;
configurationProvider->registerConfiguration("system", systemConfig);
}
return configurationProvider;
}
}}
}
}
+4 -3
View File
@@ -22,8 +22,9 @@ namespace pvAccess {
/// Byte to hexchar mapping.
static const char lookup[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
/// Get hex representation of byte.
string toHex(int8 b) {
@@ -57,7 +58,7 @@ void hexDump(std::string const & name, const int8 *bs, int start, int len) {
}
void hexDump(std::string const & prologue, string const & name, const int8 *bs,
int start, int len) {
int start, int len) {
stringstream header;
+38 -38
View File
@@ -32,8 +32,8 @@ void addDefaultBroadcastAddress(InetAddrVector* v, unsigned short p) {
v->push_back(pNewNode);
}
InetAddrVector* getBroadcastAddresses(SOCKET sock,
unsigned short defaultPort) {
InetAddrVector* getBroadcastAddresses(SOCKET sock,
unsigned short defaultPort) {
ELLLIST as;
ellInit(&as);
osiSockAddr serverAddr;
@@ -147,7 +147,7 @@ int32 parseInetAddress(const string & addr) {
}
InetAddrVector* getSocketAddressList(const std::string & list, int defaultPort,
const InetAddrVector* appendList) {
const InetAddrVector* appendList) {
InetAddrVector* iav = new InetAddrVector();
// skip leading spaces
@@ -174,13 +174,13 @@ InetAddrVector* getSocketAddressList(const std::string & list, int defaultPort,
if(appendList!=NULL) {
for(size_t i = 0; i<appendList->size(); i++)
iav->push_back((*appendList)[i]);
iav->push_back((*appendList)[i]);
}
return iav;
}
string inetAddressToString(const osiSockAddr &addr,
bool displayPort, bool displayHex) {
bool displayPort, bool displayHex) {
stringstream saddr;
int ipa = ntohl(addr.ia.sin_addr.s_addr);
@@ -191,7 +191,7 @@ string inetAddressToString(const osiSockAddr &addr,
saddr<<((int)ipa&0xFF);
if(displayPort) saddr<<":"<<ntohs(addr.ia.sin_port);
if(displayHex) saddr<<" ("<<hex<<ntohl(addr.ia.sin_addr.s_addr)
<<")";
<<")";
return saddr.str();
}
@@ -231,7 +231,7 @@ static size_t ifreqSize ( struct ifreq *pifreq )
size = ifreq_size ( pifreq );
if ( size < sizeof ( *pifreq ) ) {
size = sizeof ( *pifreq );
size = sizeof ( *pifreq );
}
return size;
}
@@ -305,8 +305,8 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
* If its not an internet interface then dont use it
*/
if ( pIfreqList->ifr_addr.sa_family != AF_INET ) {
/*ifDepenDebugPrintf ( ("discoverInterfaces(): interface \"%s\" was not AF_INET\n", pIfreqList->ifr_name) );*/
continue;
/*ifDepenDebugPrintf ( ("discoverInterfaces(): interface \"%s\" was not AF_INET\n", pIfreqList->ifr_name) );*/
continue;
}
/*
@@ -319,13 +319,13 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
continue;
}
if ( pMatchAddr->ia.sin_addr.s_addr != htonl (INADDR_ANY) ) {
struct sockaddr_in *pInetAddr = (struct sockaddr_in *) &pIfreqList->ifr_addr;
if ( pInetAddr->sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr ) {
/*ifDepenDebugPrintf ( ("discoverInterfaces(): net intf \"%s\" didnt match\n", pIfreqList->ifr_name) );*/
continue;
}
else
match = 1;
struct sockaddr_in *pInetAddr = (struct sockaddr_in *) &pIfreqList->ifr_addr;
if ( pInetAddr->sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr ) {
/*ifDepenDebugPrintf ( ("discoverInterfaces(): net intf \"%s\" didnt match\n", pIfreqList->ifr_name) );*/
continue;
}
else
match = 1;
}
}
@@ -339,8 +339,8 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
* dont bother with interfaces that have been disabled
*/
if ( ! ( pIfreqList->ifr_flags & IFF_UP ) ) {
/*ifDepenDebugPrintf ( ("discoverInterfaces(): net intf \"%s\" was down\n", pIfreqList->ifr_name) );*/
continue;
/*ifDepenDebugPrintf ( ("discoverInterfaces(): net intf \"%s\" was down\n", pIfreqList->ifr_name) );*/
continue;
}
/*
@@ -348,8 +348,8 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
*/
if (!match) {
if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
/*ifDepenDebugPrintf ( ("discoverInterfaces(): ignoring loopback interface: \"%s\"\n", pIfreqList->ifr_name) );*/
continue;
/*ifDepenDebugPrintf ( ("discoverInterfaces(): ignoring loopback interface: \"%s\"\n", pIfreqList->ifr_name) );*/
continue;
}
}
@@ -394,16 +394,16 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
/*ifDepenDebugPrintf ( ( "discoverInterfaces(): net intf \"%s\": not point to point or bcast?\n", pIfreqList->ifr_name ) );*/
continue;
}
}
}
/*ifDepenDebugPrintf ( ("discoverInterfaces(): net intf \"%s\" found\n", pIfreqList->ifr_name) );*/
/*ifDepenDebugPrintf ( ("discoverInterfaces(): net intf \"%s\" found\n", pIfreqList->ifr_name) );*/
list.push_back(node);
}
list.push_back(node);
}
free ( pIfreqList );
return 0;
}
free ( pIfreqList );
return 0;
}
#else
@@ -423,7 +423,7 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
int match;
/* only valid for winsock 2 and above
TODO resolve dllimport compilation problem and uncomment this check
TODO resolve dllimport compilation problem and uncomment this check
if (wsaMajorVersion() < 2 ) {
fprintf(stderr, "Need to set EPICS_CA_AUTO_ADDR_LIST=NO for winsock 1\n");
return -1;
@@ -432,14 +432,14 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
nelem = 100;
pIfinfoList = (INTERFACE_INFO *) calloc(nelem, sizeof(INTERFACE_INFO));
if(!pIfinfoList){
if(!pIfinfoList) {
return -1;
}
status = WSAIoctl (socket, SIO_GET_INTERFACE_LIST,
NULL, 0,
(LPVOID)pIfinfoList, nelem*sizeof(INTERFACE_INFO),
&cbBytesReturned, NULL, NULL);
NULL, 0,
(LPVOID)pIfinfoList, nelem*sizeof(INTERFACE_INFO),
&cbBytesReturned, NULL, NULL);
if (status != 0 || cbBytesReturned == 0) {
fprintf(stderr, "WSAIoctl SIO_GET_INTERFACE_LIST failed %d\n",WSAGetLastError());
@@ -448,7 +448,7 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
}
numifs = cbBytesReturned/sizeof(INTERFACE_INFO);
for (pIfinfo = pIfinfoList; pIfinfo < (pIfinfoList+numifs); pIfinfo++){
for (pIfinfo = pIfinfoList; pIfinfo < (pIfinfoList+numifs); pIfinfo++) {
/*
* dont bother with interfaces that have been disabled
@@ -504,7 +504,7 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
ifaceNode node;
node.ifaceAddr.ia = pIfinfo->iiAddress.AddressIn;
if (pIfinfo->iiFlags & IFF_BROADCAST) {
const unsigned mask = pIfinfo->iiNetmask.AddressIn.sin_addr.s_addr;
const unsigned bcast = pIfinfo->iiBroadcastAddress.AddressIn.sin_addr.s_addr;
@@ -513,11 +513,11 @@ int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *
node.ifaceBCast.ia.sin_family = AF_INET;
node.ifaceBCast.ia.sin_addr.s_addr = result;
node.ifaceBCast.ia.sin_port = htons ( 0 );
}
else {
node.ifaceBCast.ia = pIfinfo->iiBroadcastAddress.AddressIn;
}
else {
node.ifaceBCast.ia = pIfinfo->iiBroadcastAddress.AddressIn;
}
list.push_back(node);
}
+80 -79
View File
@@ -21,7 +21,7 @@ FieldCreatePtr IntrospectionRegistry::_fieldCreate(getFieldCreate());
IntrospectionRegistry::IntrospectionRegistry()
{
reset();
reset();
}
IntrospectionRegistry::~IntrospectionRegistry()
@@ -31,118 +31,119 @@ IntrospectionRegistry::~IntrospectionRegistry()
void IntrospectionRegistry::reset()
{
_pointer = 1;
_registry.clear();
_pointer = 1;
_registry.clear();
}
FieldConstPtr IntrospectionRegistry::getIntrospectionInterface(const int16 id)
{
registryMap_t::iterator registryIter = _registry.find(id);
if(registryIter == _registry.end())
{
return FieldConstPtr();
}
return registryIter->second;
registryMap_t::iterator registryIter = _registry.find(id);
if(registryIter == _registry.end())
{
return FieldConstPtr();
}
return registryIter->second;
}
void IntrospectionRegistry::registerIntrospectionInterface(const int16 id, FieldConstPtr const & field)
{
_registry[id] = field;
_registry[id] = field;
}
int16 IntrospectionRegistry::registerIntrospectionInterface(FieldConstPtr const & field, bool& existing)
{
int16 key;
// TODO this is slow
if(registryContainsValue(field, key))
{
existing = true;
}
else
{
existing = false;
key = _pointer++;
_registry[key] = field;
}
return key;
int16 key;
// TODO this is slow
if(registryContainsValue(field, key))
{
existing = true;
}
else
{
existing = false;
key = _pointer++;
_registry[key] = field;
}
return key;
}
// TODO slow !!!!
bool IntrospectionRegistry::registryContainsValue(FieldConstPtr const & field, int16& key)
{
for(registryMap_t::reverse_iterator registryRIter = _registry.rbegin(); registryRIter != _registry.rend(); registryRIter++)
{
if(*(field.get()) == *(registryRIter->second))
{
key = registryRIter->first;
return true;
}
}
return false;
for(registryMap_t::reverse_iterator registryRIter = _registry.rbegin(); registryRIter != _registry.rend(); registryRIter++)
{
if(*(field.get()) == *(registryRIter->second))
{
key = registryRIter->first;
return true;
}
}
return false;
}
void IntrospectionRegistry::serialize(FieldConstPtr const & field, ByteBuffer* buffer, SerializableControl* control)
{
if (field.get() == NULL)
{
SerializationHelper::serializeNullField(buffer, control);
}
else
{
if (field.get() == NULL)
{
SerializationHelper::serializeNullField(buffer, control);
}
else
{
// do not cache scalars, scalarArrays
// ... and (array of) variant unions - not worth the complex condition,
// unless bool Field.cache() would exist
if (field->getType() != scalar &&
field->getType() != scalarArray)
{
bool existing;
const int16 key = registerIntrospectionInterface(field, existing);
if (existing) {
control->ensureBuffer(3);
buffer->putByte(ONLY_ID_TYPE_CODE);
buffer->putShort(key);
return;
}
else {
control->ensureBuffer(3);
buffer->putByte(FULL_WITH_ID_TYPE_CODE); // could also be a mask
buffer->putShort(key);
}
}
field->getType() != scalarArray)
{
bool existing;
const int16 key = registerIntrospectionInterface(field, existing);
if (existing) {
control->ensureBuffer(3);
buffer->putByte(ONLY_ID_TYPE_CODE);
buffer->putShort(key);
return;
}
else {
control->ensureBuffer(3);
buffer->putByte(FULL_WITH_ID_TYPE_CODE); // could also be a mask
buffer->putShort(key);
}
}
field->serialize(buffer, control);
}
field->serialize(buffer, control);
}
}
FieldConstPtr IntrospectionRegistry::deserialize(ByteBuffer* buffer, DeserializableControl* control)
{
control->ensureData(1);
size_t pos = buffer->getPosition();
const int8 typeCode = buffer->getByte();
control->ensureData(1);
size_t pos = buffer->getPosition();
const int8 typeCode = buffer->getByte();
if (typeCode == NULL_TYPE_CODE)
{
if (typeCode == NULL_TYPE_CODE)
{
return FieldConstPtr();
}
else if (typeCode == ONLY_ID_TYPE_CODE)
{
control->ensureData(sizeof(int16)/sizeof(int8));
return getIntrospectionInterface(buffer->getShort());
}
// could also be a mask
if(typeCode == IntrospectionRegistry::FULL_WITH_ID_TYPE_CODE)
{
control->ensureData(sizeof(int16)/sizeof(int8));
const short key = buffer->getShort();
FieldConstPtr field = _fieldCreate->deserialize(buffer, control);
registerIntrospectionInterface(key, field);
return field;
}
}
else if (typeCode == ONLY_ID_TYPE_CODE)
{
control->ensureData(sizeof(int16)/sizeof(int8));
return getIntrospectionInterface(buffer->getShort());
}
// could also be a mask
if(typeCode == IntrospectionRegistry::FULL_WITH_ID_TYPE_CODE)
{
control->ensureData(sizeof(int16)/sizeof(int8));
const short key = buffer->getShort();
FieldConstPtr field = _fieldCreate->deserialize(buffer, control);
registerIntrospectionInterface(key, field);
return field;
}
// return typeCode back
// return typeCode back
buffer->setPosition(pos);
return _fieldCreate->deserialize(buffer, control);
return _fieldCreate->deserialize(buffer, control);
}
}}
}
}
+78 -78
View File
@@ -28,90 +28,90 @@ using std::ios;
using std::endl;
namespace epics {
namespace pvAccess {
#define TIMETEXTLEN 32
static pvAccessLogLevel g_pvAccessLogLevel = logLevelInfo;
void pvAccessLog(pvAccessLogLevel level, const char* format, ...)
{
// TODO lock
if (level >= g_pvAccessLogLevel)
{
char timeText[TIMETEXTLEN];
epicsTimeStamp tsNow;
epicsTimeGetCurrent(&tsNow);
epicsTimeToStrftime(timeText, TIMETEXTLEN, "%Y-%m-%dT%H:%M:%S.%03f", &tsNow);
printf("%s ", timeText);
namespace pvAccess {
va_list arg;
va_start(arg, format);
vprintf(format, arg);
va_end(arg);
#define TIMETEXTLEN 32
printf("\n");
fflush(stdout); // needed for WIN32
}
}
static pvAccessLogLevel g_pvAccessLogLevel = logLevelInfo;
void pvAccessSetLogLevel(pvAccessLogLevel level)
{
g_pvAccessLogLevel = level;
}
void pvAccessLog(pvAccessLogLevel level, const char* format, ...)
{
// TODO lock
if (level >= g_pvAccessLogLevel)
{
char timeText[TIMETEXTLEN];
epicsTimeStamp tsNow;
bool pvAccessIsLoggable(pvAccessLogLevel level)
{
return level >= g_pvAccessLogLevel;
}
epicsTimeGetCurrent(&tsNow);
epicsTimeToStrftime(timeText, TIMETEXTLEN, "%Y-%m-%dT%H:%M:%S.%03f", &tsNow);
class FileLogger : public NoDefaultMethods {
public:
FileLogger(std::string const & name) {
logFile.open(name.data(), ios::app);
}
printf("%s ", timeText);
~FileLogger() {
logFile.close();
}
void logMessage(const char* message) {
time_t rawtime;
time(&rawtime);
char* timeStr = ctime(&rawtime);
timeStr[strlen(timeStr)-1]='\0'; // remove newline
logFile<<timeStr<<"\t"<<message; // the newline is added by the caller
}
private:
ofstream logFile;
};
static FileLogger* fileLogger = NULL;
static void errLogFileListener(void* /*pPrivate*/, const char *message) {
fileLogger->logMessage(message);
}
static void exitFileLoggerHandler(void* /*pPrivate*/) {
errlogFlush();
delete fileLogger;
}
void createFileLogger(std::string const & fname) {
static Mutex mutex;
Lock xx(mutex);
if(fileLogger==NULL) {
fileLogger = new FileLogger(fname);
errlogInit(2048);
errlogAddListener(errLogFileListener, NULL);
epicsAtExit(exitFileLoggerHandler, NULL);
}
}
va_list arg;
va_start(arg, format);
vprintf(format, arg);
va_end(arg);
printf("\n");
fflush(stdout); // needed for WIN32
}
}
void pvAccessSetLogLevel(pvAccessLogLevel level)
{
g_pvAccessLogLevel = level;
}
bool pvAccessIsLoggable(pvAccessLogLevel level)
{
return level >= g_pvAccessLogLevel;
}
class FileLogger : public NoDefaultMethods {
public:
FileLogger(std::string const & name) {
logFile.open(name.data(), ios::app);
}
~FileLogger() {
logFile.close();
}
void logMessage(const char* message) {
time_t rawtime;
time(&rawtime);
char* timeStr = ctime(&rawtime);
timeStr[strlen(timeStr)-1]='\0'; // remove newline
logFile<<timeStr<<"\t"<<message; // the newline is added by the caller
}
private:
ofstream logFile;
};
static FileLogger* fileLogger = NULL;
static void errLogFileListener(void* /*pPrivate*/, const char *message) {
fileLogger->logMessage(message);
}
static void exitFileLoggerHandler(void* /*pPrivate*/) {
errlogFlush();
delete fileLogger;
}
void createFileLogger(std::string const & fname) {
static Mutex mutex;
Lock xx(mutex);
if(fileLogger==NULL) {
fileLogger = new FileLogger(fname);
errlogInit(2048);
errlogAddListener(errLogFileListener, NULL);
epicsAtExit(exitFileLoggerHandler, NULL);
}
}
}
}
+119 -108
View File
@@ -43,27 +43,35 @@ public:
Properties(const std::string &fileName) EPICS_DEPRECATED;
inline void setProperty(const std::string &key,const std::string &value)
{ _properties[key] = value; }
{
_properties[key] = value;
}
const std::string& getProperty(const std::string &key) const;
const std::string& getProperty(const std::string &key, const std::string &defaultValue) const;
inline bool hasProperty(const std::string &key) const
{ return _properties.find(key) != _properties.end(); }
{
return _properties.find(key) != _properties.end();
}
void store() const;
void store(const std::string &fileName) const;
void store(std::ostream& strm) const;
void load();
void load(const std::string &fileName);
void load(const std::string &fileName);
void load(std::istream& strm);
void list();
void list();
inline size_t size() const {return _properties.size();}
inline size_t size() const {
return _properties.size();
}
private:
typedef std::map<std::string,std::string> _properties_t;
_properties_t _properties;
std::string _fileName;
public:
inline const _properties_t& map() const {return _properties;}
inline const _properties_t& map() const {
return _properties;
}
};
class ConfigurationStack;
@@ -74,72 +82,72 @@ class ConfigurationStack;
class epicsShareClass Configuration : private epics::pvData::NoDefaultMethods
{
public:
POINTER_DEFINITIONS(Configuration);
POINTER_DEFINITIONS(Configuration);
/**
* Destructor.
*/
virtual ~Configuration() {};
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as bool or default value if it does not exist.
*/
bool getPropertyAsBoolean(const std::string &name, const bool defaultValue) const;
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as int32 or default value if it does not exist.
*/
epics::pvData::int32 getPropertyAsInteger(const std::string &name, const epics::pvData::int32 defaultValue) const;
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as float or default value if it does not exist.
*/
float getPropertyAsFloat(const std::string &name, const float defaultValue) const;
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as double or default value if it does not exist.
*/
double getPropertyAsDouble(const std::string &name, const double defaultValue) const;
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as std::string or default value if it does not exist.
*/
std::string getPropertyAsString(const std::string &name, const std::string &defaultValue) const;
/**
* Fetch and parse as a socket address and port number (address family set accordingly).
* At present only numeric addresses are parsed (eg. "127.0.0.1:4242").
*
* The storage pointed to be addr should be initialized with a default value, or zeroed.
/**
* Destructor.
*/
virtual ~Configuration() {};
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @pram addr pointer to the address struct to be filled in
* @return true if addr now contains an address, false otherwise
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as bool or default value if it does not exist.
*/
bool getPropertyAsBoolean(const std::string &name, const bool defaultValue) const;
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as int32 or default value if it does not exist.
*/
epics::pvData::int32 getPropertyAsInteger(const std::string &name, const epics::pvData::int32 defaultValue) const;
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as float or default value if it does not exist.
*/
float getPropertyAsFloat(const std::string &name, const float defaultValue) const;
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as double or default value if it does not exist.
*/
double getPropertyAsDouble(const std::string &name, const double defaultValue) const;
/**
* Get the environment variable specified by name or return default value
* if it does not exist.
*
* @param name name of the environment variable to return.
* @param defualtValue default value to return if environment variable does not exists.
*
* @return environment variable value as std::string or default value if it does not exist.
*/
std::string getPropertyAsString(const std::string &name, const std::string &defaultValue) const;
/**
* Fetch and parse as a socket address and port number (address family set accordingly).
* At present only numeric addresses are parsed (eg. "127.0.0.1:4242").
*
* The storage pointed to be addr should be initialized with a default value, or zeroed.
*
* @param name name of the environment variable to return.
* @pram addr pointer to the address struct to be filled in
* @return true if addr now contains an address, false otherwise
*/
bool getPropertyAsAddress(const std::string& name, osiSockAddr* addr) const;
bool hasProperty(const std::string &name) const;
@@ -188,7 +196,9 @@ public:
confs.pop_back();
return ret;
}
inline size_t size() const {return confs.size();}
inline size_t size() const {
return confs.size();
}
};
struct epicsShareClass ConfigurationBuilder
@@ -218,41 +228,41 @@ private:
class epicsShareClass ConfigurationProvider : private epics::pvData::NoDefaultMethods
{
public:
POINTER_DEFINITIONS(ConfigurationProvider);
/**
* Destructor.
*/
virtual ~ConfigurationProvider() {};
/**
* Return configuration specified by name.
*
* @param name name of the configuration to return.
*
* @return configuration specified by name or NULL if it does not exists.
*/
virtual Configuration::shared_pointer getConfiguration(const std::string &name) = 0;
/**
* Register configuration.
*
* @param name name of the configuration to register.
* @param configuration configuration to register.
*/
virtual void registerConfiguration(const std::string &name, Configuration::shared_pointer const & configuration) = 0;
POINTER_DEFINITIONS(ConfigurationProvider);
/**
* Destructor.
*/
virtual ~ConfigurationProvider() {};
/**
* Return configuration specified by name.
*
* @param name name of the configuration to return.
*
* @return configuration specified by name or NULL if it does not exists.
*/
virtual Configuration::shared_pointer getConfiguration(const std::string &name) = 0;
/**
* Register configuration.
*
* @param name name of the configuration to register.
* @param configuration configuration to register.
*/
virtual void registerConfiguration(const std::string &name, Configuration::shared_pointer const & configuration) = 0;
};
class ConfigurationProviderImpl: public ConfigurationProvider
{
public:
ConfigurationProviderImpl() {}
/**
* Destructor. Note: Registered configurations will be deleted!!
*/
/**
* Destructor. Note: Registered configurations will be deleted!!
*/
~ConfigurationProviderImpl() {}
Configuration::shared_pointer getConfiguration(const std::string &name);
void registerConfiguration(const std::string &name, Configuration::shared_pointer const & configuration);
Configuration::shared_pointer getConfiguration(const std::string &name);
void registerConfiguration(const std::string &name, Configuration::shared_pointer const & configuration);
private:
epics::pvData::Mutex _mutex;
std::map<std::string,Configuration::shared_pointer> _configs;
epics::pvData::Mutex _mutex;
std::map<std::string,Configuration::shared_pointer> _configs;
};
/**
@@ -261,17 +271,17 @@ private:
class epicsShareClass ConfigurationFactory : private epics::pvData::NoDefaultMethods
{
public:
POINTER_DEFINITIONS(ConfigurationFactory);
POINTER_DEFINITIONS(ConfigurationFactory);
/**
* Lazily creates configuration provider.
*
* @param name name of the configuration to register.
* @param configuration configuration to register.
*
* @return configuration provider
*/
static ConfigurationProvider::shared_pointer getProvider();
/**
* Lazily creates configuration provider.
*
* @param name name of the configuration to register.
* @param configuration configuration to register.
*
* @return configuration provider
*/
static ConfigurationProvider::shared_pointer getProvider();
static void registerConfiguration(const std::string &name, Configuration::shared_pointer const & configuration)
{
getProvider()->registerConfiguration(name, configuration);
@@ -282,9 +292,10 @@ public:
}
private:
ConfigurationFactory() {};
ConfigurationFactory() {};
};
}}
}
}
#endif /* CONFIGURATION_H */
+5 -3
View File
@@ -27,7 +27,8 @@
#include <shareLib.h>
namespace epics {namespace pvAccess {
namespace epics {
namespace pvAccess {
/** @brief An intrusive, loss-less, unbounded, round-robin queue
@@ -82,7 +83,7 @@ public:
public:
entry() :Qcnt(0), holder()
#ifndef NDEBUG
, owner(NULL)
, owner(NULL)
#endif
{
enode.node.next = enode.node.previous = NULL;
@@ -196,6 +197,7 @@ private:
mutable epicsEvent wakeup;
};
}} // namespace
}
} // namespace
#endif // FAIRQUEUE_H
+25 -25
View File
@@ -24,33 +24,33 @@
namespace epics {
namespace pvAccess {
/**
* Output a buffer in hex format.
* @param name name (description) of the message.
* @param bs buffer to dump
* @param len first bytes (length) to dump.
*/
epicsShareFunc void hexDump(std::string const & name, const epics::pvData::int8 *bs, int len);
/**
* Output a buffer in hex format.
* @param name name (description) of the message.
* @param bs buffer to dump
* @param len first bytes (length) to dump.
*/
epicsShareFunc void hexDump(std::string const & name, const epics::pvData::int8 *bs, int len);
/**
* Output a buffer in hex format.
* @param[in] name name (description) of the message.
* @param[in] bs buffer to dump
* @param[in] start dump message using given offset.
* @param[in] len first bytes (length) to dump.
*/
epicsShareFunc void hexDump(std::string const & name, const epics::pvData::int8 *bs, int start, int len);
/**
* Output a buffer in hex format.
* @param[in] name name (description) of the message.
* @param[in] bs buffer to dump
* @param[in] start dump message using given offset.
* @param[in] len first bytes (length) to dump.
*/
epicsShareFunc void hexDump(std::string const & name, const epics::pvData::int8 *bs, int start, int len);
/**
* Output a buffer in hex format.
* @param[in] prologue string to prefixed to debug output, can be <code>null</code>
* @param[in] name name (description) of the message.
* @param[in] bs buffer to dump
* @param[in] start dump message using given offset.
* @param[in] len first bytes (length) to dump.
*/
epicsShareFunc void hexDump(std::string const & prologue, std::string const & name,
const epics::pvData::int8 *bs, int start, int len);
/**
* Output a buffer in hex format.
* @param[in] prologue string to prefixed to debug output, can be <code>null</code>
* @param[in] name name (description) of the message.
* @param[in] bs buffer to dump
* @param[in] start dump message using given offset.
* @param[in] len first bytes (length) to dump.
*/
epicsShareFunc void hexDump(std::string const & prologue, std::string const & name,
const epics::pvData::int8 *bs, int start, int len);
}
}
+96 -96
View File
@@ -32,118 +32,118 @@
namespace epics {
namespace pvAccess {
typedef std::vector<osiSockAddr> InetAddrVector;
typedef std::vector<osiSockAddr> InetAddrVector;
/**
* Returns a vector containing all the IPv4 broadcast addresses on this machine.
* IPv6 doesn't have a local broadcast address.
* Conversion of the defaultPort to network byte order performed by
* the function.
*/
epicsShareFunc InetAddrVector* getBroadcastAddresses(SOCKET sock, unsigned short defaultPort);
/**
* Returns a vector containing all the IPv4 broadcast addresses on this machine.
* IPv6 doesn't have a local broadcast address.
* Conversion of the defaultPort to network byte order performed by
* the function.
*/
epicsShareFunc InetAddrVector* getBroadcastAddresses(SOCKET sock, unsigned short defaultPort);
struct ifaceNode {
osiSockAddr ifaceAddr, ifaceBCast;
};
typedef std::vector<ifaceNode> IfaceNodeVector;
epicsShareFunc int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *pMatchAddr = 0);
struct ifaceNode {
osiSockAddr ifaceAddr, ifaceBCast;
};
typedef std::vector<ifaceNode> IfaceNodeVector;
epicsShareFunc int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *pMatchAddr = 0);
/**
* Returns NIF index for given interface address, or -1 on failure.
*/
epicsShareFunc int discoverInterfaceIndex(SOCKET socket, const osiSockAddr *pMatchAddr);
/**
* Returns NIF index for given interface address, or -1 on failure.
*/
epicsShareFunc int discoverInterfaceIndex(SOCKET socket, const osiSockAddr *pMatchAddr);
/**
* Encode IPv4 address as IPv6 address.
* @param buffer byte-buffer where to put encoded data.
* @param address address to encode.
*/
epicsShareFunc void encodeAsIPv6Address(epics::pvData::ByteBuffer* buffer, const osiSockAddr* address);
/**
* Encode IPv4 address as IPv6 address.
* @param buffer byte-buffer where to put encoded data.
* @param address address to encode.
*/
epicsShareFunc void encodeAsIPv6Address(epics::pvData::ByteBuffer* buffer, const osiSockAddr* address);
/**
* Decode IPv6 address (as IPv4 address).
* @param buffer byte-buffer where to get encoded data.
* @param address address where to decode.
* @return success status (true on success).
*/
epicsShareFunc bool decodeAsIPv6Address(epics::pvData::ByteBuffer* buffer, osiSockAddr* address);
/**
* Decode IPv6 address (as IPv4 address).
* @param buffer byte-buffer where to get encoded data.
* @param address address where to decode.
* @return success status (true on success).
*/
epicsShareFunc bool decodeAsIPv6Address(epics::pvData::ByteBuffer* buffer, osiSockAddr* address);
/**
* Check if an IPv4 address is a multicast address.
* @param address IPv4 address to check.
* @return true if the adress is a multicast address.
*/
epicsShareFunc bool isMulticastAddress(const osiSockAddr* address);
/**
* Check if an IPv4 address is a multicast address.
* @param address IPv4 address to check.
* @return true if the adress is a multicast address.
*/
epicsShareFunc bool isMulticastAddress(const osiSockAddr* address);
/**
* Convert an integer into an IPv4 INET address.
* @param addr integer representation of a given address.
* @return IPv4 INET address.
*/
epicsShareFunc osiSockAddr* intToIPv4Address(epics::pvData::int32 addr);
/**
* Convert an integer into an IPv4 INET address.
* @param addr integer representation of a given address.
* @return IPv4 INET address.
*/
epicsShareFunc osiSockAddr* intToIPv4Address(epics::pvData::int32 addr);
/**
* Convert an IPv4 INET address to an integer.
* @param addr IPv4 INET address.
* @return integer representation of a given address.
*/
epicsShareFunc epics::pvData::int32 ipv4AddressToInt(const osiSockAddr& addr);
/**
* Convert an IPv4 INET address to an integer.
* @param addr IPv4 INET address.
* @return integer representation of a given address.
*/
epicsShareFunc epics::pvData::int32 ipv4AddressToInt(const osiSockAddr& addr);
/**
* Parse space delimited addresss[:port] string and return array of <code>InetSocketAddress</code>.
* @param list space delimited addresss[:port] string.
* @param defaultPort port take if not specified.
* @param appendList list to be appended.
* @return array of <code>InetSocketAddress</code>.
*/
epicsShareFunc InetAddrVector* getSocketAddressList(const std::string & list, int defaultPort,
const InetAddrVector* appendList = NULL);
/**
* Parse space delimited addresss[:port] string and return array of <code>InetSocketAddress</code>.
* @param list space delimited addresss[:port] string.
* @param defaultPort port take if not specified.
* @param appendList list to be appended.
* @return array of <code>InetSocketAddress</code>.
*/
epicsShareFunc InetAddrVector* getSocketAddressList(const std::string & list, int defaultPort,
const InetAddrVector* appendList = NULL);
epicsShareFunc std::string inetAddressToString(const osiSockAddr &addr,
bool displayPort = true, bool displayHex = false);
epicsShareFunc std::string inetAddressToString(const osiSockAddr &addr,
bool displayPort = true, bool displayHex = false);
epicsShareFunc int getLoopbackNIF(osiSockAddr& loAddr, std::string const & localNIF, unsigned short port);
epicsShareFunc int getLoopbackNIF(osiSockAddr& loAddr, std::string const & localNIF, unsigned short port);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// comparators for osiSockAddr
// comparators for osiSockAddr
struct comp_osiSockAddrPtr {
bool operator()(osiSockAddr const *a, osiSockAddr const *b) const {
if(a->sa.sa_family<b->sa.sa_family) return true;
if((a->sa.sa_family==b->sa.sa_family)&&(a->ia.sin_addr.s_addr
<b->ia.sin_addr.s_addr)) return true;
if((a->sa.sa_family==b->sa.sa_family)&&(a->ia.sin_addr.s_addr
==b->ia.sin_addr.s_addr)&&(a->ia.sin_port
<b->ia.sin_port)) return true;
return false;
}
};
struct comp_osiSockAddrPtr {
bool operator()(osiSockAddr const *a, osiSockAddr const *b) const {
if(a->sa.sa_family<b->sa.sa_family) return true;
if((a->sa.sa_family==b->sa.sa_family)&&(a->ia.sin_addr.s_addr
<b->ia.sin_addr.s_addr)) return true;
if((a->sa.sa_family==b->sa.sa_family)&&(a->ia.sin_addr.s_addr
==b->ia.sin_addr.s_addr)&&(a->ia.sin_port
<b->ia.sin_port)) return true;
return false;
}
};
struct comp_osiSock_lt {
bool operator()(const osiSockAddr& a, const osiSockAddr& b) const {
if(a.sa.sa_family<b.sa.sa_family) return true;
if((a.sa.sa_family==b.sa.sa_family)&&(a.ia.sin_addr.s_addr
<b.ia.sin_addr.s_addr)) return true;
if((a.sa.sa_family==b.sa.sa_family)&&(a.ia.sin_addr.s_addr
==b.ia.sin_addr.s_addr)&&(a.ia.sin_port
<b.ia.sin_port)) return true;
return false;
}
};
struct comp_osiSock_lt {
bool operator()(const osiSockAddr& a, const osiSockAddr& b) const {
if(a.sa.sa_family<b.sa.sa_family) return true;
if((a.sa.sa_family==b.sa.sa_family)&&(a.ia.sin_addr.s_addr
<b.ia.sin_addr.s_addr)) return true;
if((a.sa.sa_family==b.sa.sa_family)&&(a.ia.sin_addr.s_addr
==b.ia.sin_addr.s_addr)&&(a.ia.sin_port
<b.ia.sin_port)) return true;
return false;
}
};
//TODO if unordered map is used instead of map we can use sockAddrAreIdentical routine from osiSock.h
struct comp_osiSockAddr {
bool operator()(osiSockAddr const a, osiSockAddr const b) const {
if(a.sa.sa_family<b.sa.sa_family) return true;
if((a.sa.sa_family==b.sa.sa_family)&&(a.ia.sin_addr.s_addr
<b.ia.sin_addr.s_addr)) return true;
if((a.sa.sa_family==b.sa.sa_family)&&(a.ia.sin_addr.s_addr
==b.ia.sin_addr.s_addr)&&(a.ia.sin_port
<b.ia.sin_port)) return true;
return false;
}
};
//TODO if unordered map is used instead of map we can use sockAddrAreIdentical routine from osiSock.h
struct comp_osiSockAddr {
bool operator()(osiSockAddr const a, osiSockAddr const b) const {
if(a.sa.sa_family<b.sa.sa_family) return true;
if((a.sa.sa_family==b.sa.sa_family)&&(a.ia.sin_addr.s_addr
<b.ia.sin_addr.s_addr)) return true;
if((a.sa.sa_family==b.sa.sa_family)&&(a.ia.sin_addr.s_addr
==b.ia.sin_addr.s_addr)&&(a.ia.sin_port
<b.ia.sin_port)) return true;
return false;
}
};
}
}
+81 -80
View File
@@ -37,97 +37,98 @@ namespace pvAccess {
typedef std::map<const short,epics::pvData::FieldConstPtr> registryMap_t;
/**
* PVData Structure registry.
* Registry is used to cache introspection interfaces to minimize network traffic.
* @author gjansa
*/
class IntrospectionRegistry : public epics::pvData::NoDefaultMethods {
public:
IntrospectionRegistry();
virtual ~IntrospectionRegistry();
/**
* PVData Structure registry.
* Registry is used to cache introspection interfaces to minimize network traffic.
* @author gjansa
*/
class IntrospectionRegistry : public epics::pvData::NoDefaultMethods {
public:
IntrospectionRegistry();
virtual ~IntrospectionRegistry();
/**
* Resets registry, i.e. must be done when transport is changed (server restarted).
*/
void reset();
/**
* Get introspection interface for given ID.
*
* @param id id of the introspection interface to get
*
* @return <code>Field</code> instance for given ID.
*/
epics::pvData::FieldConstPtr getIntrospectionInterface(const epics::pvData::int16 id);
/**
* Resets registry, i.e. must be done when transport is changed (server restarted).
*/
void reset();
/**
* Get introspection interface for given ID.
*
* @param id id of the introspection interface to get
*
* @return <code>Field</code> instance for given ID.
*/
epics::pvData::FieldConstPtr getIntrospectionInterface(const epics::pvData::int16 id);
/**
* Registers introspection interface with given ID. Always INCOMING.
*
* @param id id of the introspection interface to register
* @param field introspection interface to register
*/
void registerIntrospectionInterface(const epics::pvData::int16 id, epics::pvData::FieldConstPtr const & field);
/**
* Registers introspection interface with given ID. Always INCOMING.
*
* @param id id of the introspection interface to register
* @param field introspection interface to register
*/
void registerIntrospectionInterface(const epics::pvData::int16 id, epics::pvData::FieldConstPtr const & field);
/**
* Registers introspection interface and get it's ID. Always OUTGOING.
* If it is already registered only preassigned ID is returned.
*
* TODO !!!!!!this can get very slow in large maps. We need to change this !!!!!!
*
* @param field introspection interface to register
*
* @return id of given introspection interface
*/
epics::pvData::int16 registerIntrospectionInterface(epics::pvData::FieldConstPtr const & field, bool& existing);
/**
* Registers introspection interface and get it's ID. Always OUTGOING.
* If it is already registered only preassigned ID is returned.
*
* TODO !!!!!!this can get very slow in large maps. We need to change this !!!!!!
*
* @param field introspection interface to register
*
* @return id of given introspection interface
*/
epics::pvData::int16 registerIntrospectionInterface(epics::pvData::FieldConstPtr const & field, bool& existing);
/**
* Serializes introspection interface
*
* @param field
* @param buffer
* @param control
*/
void serialize(epics::pvData::FieldConstPtr const & field, epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control);
/**
* Serializes introspection interface
*
* @param field
* @param buffer
* @param control
*/
void serialize(epics::pvData::FieldConstPtr const & field, epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control);
/**
* Deserializes introspection interface
*
* TODO
*
* @param buffer
* @param control
*
* @return <code>Field</code> deserialized from the buffer.
*/
epics::pvData::FieldConstPtr deserialize(epics::pvData::ByteBuffer* buffer, epics::pvData::DeserializableControl* control);
/**
* Deserializes introspection interface
*
* TODO
*
* @param buffer
* @param control
*
* @return <code>Field</code> deserialized from the buffer.
*/
epics::pvData::FieldConstPtr deserialize(epics::pvData::ByteBuffer* buffer, epics::pvData::DeserializableControl* control);
/**
* Null type.
*/
const static epics::pvData::int8 NULL_TYPE_CODE;
/**
* Null type.
*/
const static epics::pvData::int8 NULL_TYPE_CODE;
/**
* Serialization contains only an ID (that was assigned by one of the previous <code>FULL_WITH_ID</code> descriptions).
*/
const static epics::pvData::int8 ONLY_ID_TYPE_CODE;
/**
* Serialization contains only an ID (that was assigned by one of the previous <code>FULL_WITH_ID</code> descriptions).
*/
const static epics::pvData::int8 ONLY_ID_TYPE_CODE;
/**
* Serialization contains an ID (that can be used later, if cached) and full interface description.
*/
const static epics::pvData::int8 FULL_WITH_ID_TYPE_CODE;
/**
* Serialization contains an ID (that can be used later, if cached) and full interface description.
*/
const static epics::pvData::int8 FULL_WITH_ID_TYPE_CODE;
private:
registryMap_t _registry;
epics::pvData::int16 _pointer;
private:
registryMap_t _registry;
epics::pvData::int16 _pointer;
/**
* Field factory.
*/
static epics::pvData::FieldCreatePtr _fieldCreate;
/**
* Field factory.
*/
static epics::pvData::FieldCreatePtr _fieldCreate;
bool registryContainsValue(epics::pvData::FieldConstPtr const & field, epics::pvData::int16& key);
};
bool registryContainsValue(epics::pvData::FieldConstPtr const & field, epics::pvData::int16& key);
};
}}
}
}
#endif /* INTROSPECTIONREGISTRY_H */
+4 -4
View File
@@ -8,11 +8,11 @@
#define LIKELY_H_
#if defined(__GNUC__) && __GNUC__ >= 3
#define likely(x) __builtin_expect (x, 1)
#define unlikely(x) __builtin_expect (x, 0)
#define likely(x) __builtin_expect (x, 1)
#define unlikely(x) __builtin_expect (x, 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#define likely(x) (x)
#define unlikely(x) (x)
#endif
#endif /* LIKELY_H_ */
+52 -51
View File
@@ -24,58 +24,59 @@
namespace epics {
namespace pvAccess {
typedef enum { logLevelAll = 0, logLevelTrace, logLevelDebug, logLevelInfo,
logLevelWarn, logLevelError, logLevelFatal, logLevelOff } pvAccessLogLevel;
/*
ALL
The ALL has the lowest possible rank and is intended to turn on all logging.
TRACE
The TRACE Level designates finer-grained informational events than the DEBUG
DEBUG
The DEBUG Level designates fine-grained informational events that are most useful to debug an application.
INFO
The INFO level designates informational messages that highlight the progress of the application at coarse-grained level.
WARN
The WARN level designates potentially harmful situations.
ERROR
The ERROR level designates error events that might still allow the application to continue running.
FATAL
The FATAL level designates very severe error events that will presumably lead the application to abort.
OFF
The OFF has the highest possible rank and is intended to turn off logging.
typedef enum { logLevelAll = 0, logLevelTrace, logLevelDebug, logLevelInfo,
logLevelWarn, logLevelError, logLevelFatal, logLevelOff
} pvAccessLogLevel;
/*
ALL
The ALL has the lowest possible rank and is intended to turn on all logging.
TRACE
The TRACE Level designates finer-grained informational events than the DEBUG
DEBUG
The DEBUG Level designates fine-grained informational events that are most useful to debug an application.
INFO
The INFO level designates informational messages that highlight the progress of the application at coarse-grained level.
WARN
The WARN level designates potentially harmful situations.
ERROR
The ERROR level designates error events that might still allow the application to continue running.
FATAL
The FATAL level designates very severe error events that will presumably lead the application to abort.
OFF
The OFF has the highest possible rank and is intended to turn off logging.
*/
epicsShareExtern void pvAccessLog(pvAccessLogLevel level, const char* format, ...);
epicsShareExtern void pvAccessSetLogLevel(pvAccessLogLevel level);
epicsShareExtern bool pvAccessIsLoggable(pvAccessLogLevel level);
#if defined (__GNUC__) && __GNUC__ < 3
#define LOG(level, format, ARGS...) pvAccessLog(level, format, ##ARGS)
#else
#define LOG(level, format, ...) pvAccessLog(level, format, ##__VA_ARGS__)
#endif
#define SET_LOG_LEVEL(level) pvAccessSetLogLevel(level)
#define IS_LOGGABLE(level) pvAccessIsLoggable(level)
// EPICS errlog
//#define LOG errlogSevPrintf
//#define SET_LOG_LEVEL(level) errlogSetSevToLog(level)
// none
//#define LOG(level, fmt, ...)
//#define SET_LOG_LEVEL(level)
/**
* Create a logger that will write to file indicated by the <tt>fname</tt>.
* After creation you are free to use standard EPICSv3 functions from
* <tt>errlog.h</tt>.
*
* @param[in] fname The file to write to. If the file exists, it
* is opened for append.
*/
epicsShareExtern void pvAccessLog(pvAccessLogLevel level, const char* format, ...);
epicsShareExtern void pvAccessSetLogLevel(pvAccessLogLevel level);
epicsShareExtern bool pvAccessIsLoggable(pvAccessLogLevel level);
#if defined (__GNUC__) && __GNUC__ < 3
#define LOG(level, format, ARGS...) pvAccessLog(level, format, ##ARGS)
#else
#define LOG(level, format, ...) pvAccessLog(level, format, ##__VA_ARGS__)
#endif
#define SET_LOG_LEVEL(level) pvAccessSetLogLevel(level)
#define IS_LOGGABLE(level) pvAccessIsLoggable(level)
// EPICS errlog
//#define LOG errlogSevPrintf
//#define SET_LOG_LEVEL(level) errlogSetSevToLog(level)
// none
//#define LOG(level, fmt, ...)
//#define SET_LOG_LEVEL(level)
/**
* Create a logger that will write to file indicated by the <tt>fname</tt>.
* After creation you are free to use standard EPICSv3 functions from
* <tt>errlog.h</tt>.
*
* @param[in] fname The file to write to. If the file exists, it
* is opened for append.
*/
epicsShareExtern void createFileLogger( std::string const & fname );
epicsShareExtern void createFileLogger( std::string const & fname );
}
}
+94 -87
View File
@@ -28,7 +28,8 @@
// TODO implement using smart pointers
namespace epics { namespace pvAccess {
namespace epics {
namespace pvAccess {
/**
* NamedLockPattern
@@ -37,125 +38,131 @@ template <class Key, class Compare = std::less<Key> >
class NamedLockPattern
{
public:
/**
* Constructor.
*/
NamedLockPattern() {};
/**
* Destructor.
*/
virtual ~NamedLockPattern() {};
/**
* Acquire synchronization lock for named object.
*
* NOTE: Argument msecs is currently not supported due to
* Darwin OS not supporting pthread_mutex_timedlock. May be changed in the future.
*
* @param name name of the object whose lock to acquire.
* @param msec the number of milleseconds to wait.
* An argument less than or equal to zero means not to wait at all.
* @return <code>true</code> if acquired, <code>false</code> othwerwise.
* NOTE: currently this routine always returns true. Look above for explanation.
*/
bool acquireSynchronizationObject(const Key& name, const epics::pvData::int64 msec);
/**
* Release synchronization lock for named object.
* @param name name of the object whose lock to release.
*/
void releaseSynchronizationObject(const Key& name);
/**
* Constructor.
*/
NamedLockPattern() {};
/**
* Destructor.
*/
virtual ~NamedLockPattern() {};
/**
* Acquire synchronization lock for named object.
*
* NOTE: Argument msecs is currently not supported due to
* Darwin OS not supporting pthread_mutex_timedlock. May be changed in the future.
*
* @param name name of the object whose lock to acquire.
* @param msec the number of milleseconds to wait.
* An argument less than or equal to zero means not to wait at all.
* @return <code>true</code> if acquired, <code>false</code> othwerwise.
* NOTE: currently this routine always returns true. Look above for explanation.
*/
bool acquireSynchronizationObject(const Key& name, const epics::pvData::int64 msec);
/**
* Release synchronization lock for named object.
* @param name name of the object whose lock to release.
*/
void releaseSynchronizationObject(const Key& name);
private:
epics::pvData::Mutex _mutex;
std::map<const Key,ReferenceCountingLock::shared_pointer,Compare> _namedLocks;
typename std::map<const Key,ReferenceCountingLock::shared_pointer,Compare>::iterator _namedLocksIter;
epics::pvData::Mutex _mutex;
std::map<const Key,ReferenceCountingLock::shared_pointer,Compare> _namedLocks;
typename std::map<const Key,ReferenceCountingLock::shared_pointer,Compare>::iterator _namedLocksIter;
/**
* Release synchronization lock for named object.
* @param name name of the object whose lock to release.
* @param release set to <code>false</code> if there is no need to call release
* on synchronization lock.
*/
void releaseSynchronizationObject(const Key& name,const bool release);
/**
* Release synchronization lock for named object.
* @param name name of the object whose lock to release.
* @param release set to <code>false</code> if there is no need to call release
* on synchronization lock.
*/
void releaseSynchronizationObject(const Key& name,const bool release);
};
template <class Key, class Compare>
bool NamedLockPattern<Key,Compare>::acquireSynchronizationObject(const Key& name, const epics::pvData::int64 msec)
{
ReferenceCountingLock::shared_pointer lock;
{ //due to guard
epics::pvData::Lock guard(_mutex);
ReferenceCountingLock::shared_pointer lock;
{ //due to guard
epics::pvData::Lock guard(_mutex);
_namedLocksIter = _namedLocks.find(name);
// get synchronization object
_namedLocksIter = _namedLocks.find(name);
// get synchronization object
// none is found, create and return new one
// increment references
if(_namedLocksIter == _namedLocks.end())
{
lock.reset(new ReferenceCountingLock());
_namedLocks[name] = lock;
}
else
{
lock = _namedLocksIter->second;
lock->increment();
}
} // end of guarded area
// none is found, create and return new one
// increment references
if(_namedLocksIter == _namedLocks.end())
{
lock.reset(new ReferenceCountingLock());
_namedLocks[name] = lock;
}
else
{
lock = _namedLocksIter->second;
lock->increment();
}
} // end of guarded area
bool success = lock->acquire(msec);
bool success = lock->acquire(msec);
if(!success)
{
releaseSynchronizationObject(name, false);
}
if(!success)
{
releaseSynchronizationObject(name, false);
}
return success;
return success;
}
template <class Key, class Compare>
void NamedLockPattern<Key,Compare>::releaseSynchronizationObject(const Key& name)
{
releaseSynchronizationObject(name, true);
releaseSynchronizationObject(name, true);
}
template <class Key, class Compare>
void NamedLockPattern<Key,Compare>::releaseSynchronizationObject(const Key& name,const bool release)
{
epics::pvData::Lock guard(_mutex);
ReferenceCountingLock::shared_pointer lock;
_namedLocksIter = _namedLocks.find(name);
epics::pvData::Lock guard(_mutex);
ReferenceCountingLock::shared_pointer lock;
_namedLocksIter = _namedLocks.find(name);
// release lock
if (_namedLocksIter != _namedLocks.end())
{
lock = _namedLocksIter->second;
// release lock
if (_namedLocksIter != _namedLocks.end())
{
lock = _namedLocksIter->second;
// release the lock
if (release)
{
lock->release();
}
// release the lock
if (release)
{
lock->release();
}
// if there only one current lock exists
// remove it from the map
if (lock->decrement() <= 0)
{
_namedLocks.erase(_namedLocksIter);
}
}
// if there only one current lock exists
// remove it from the map
if (lock->decrement() <= 0)
{
_namedLocks.erase(_namedLocksIter);
}
}
}
template <class Key, class Compare>
class NamedLock : private epics::pvData::NoDefaultMethods
{
public:
NamedLock(NamedLockPattern<Key,Compare>* namedLockPattern): _namedLockPattern(namedLockPattern) {}
bool acquireSynchronizationObject(const Key& name, const epics::pvData::int64 msec) {_name = name; return _namedLockPattern->acquireSynchronizationObject(name,msec);}
~NamedLock(){_namedLockPattern->releaseSynchronizationObject(_name);}
NamedLock(NamedLockPattern<Key,Compare>* namedLockPattern): _namedLockPattern(namedLockPattern) {}
bool acquireSynchronizationObject(const Key& name, const epics::pvData::int64 msec) {
_name = name;
return _namedLockPattern->acquireSynchronizationObject(name,msec);
}
~NamedLock() {
_namedLockPattern->releaseSynchronizationObject(_name);
}
private:
Key _name;
NamedLockPattern<Key,Compare>* _namedLockPattern;
Key _name;
NamedLockPattern<Key,Compare>* _namedLockPattern;
};
}}
}
}
#endif /* NAMEDLOCKPATTERN_H */
+45 -44
View File
@@ -3,7 +3,7 @@
* pvAccessCPP is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
#ifndef REFERENCECOUNTINGLOCK_H
#define REFERENCECOUNTINGLOCK_H
@@ -37,51 +37,52 @@ class ReferenceCountingLock
public:
POINTER_DEFINITIONS(ReferenceCountingLock);
/**
* Constructor of <code>ReferenceCountingLock</code>.
* After construction lock is free and reference count equals <code>1</code>.
*/
ReferenceCountingLock();
/**
* Destructor of <code>ReferenceCountingLock</code>.
*/
virtual ~ReferenceCountingLock();
/**
* Attempt to acquire lock.
*
* NOTE: Argument msecs is currently not supported due to
* Darwin OS not supporting pthread_mutex_timedlock. May be changed in the future.
*
* @param msecs the number of milleseconds to wait.
* An argument less than or equal to zero means not to wait at all.
*
* @return <code>true</code> if acquired, <code>false</code> otherwise.
* NOTE: currently this routine always returns true. Look above for explanation.
*
*/
bool acquire(epics::pvData::int64 msecs);
/**
* Release previously acquired lock.
*/
void release();
/**
* Increment number of references.
*
* @return number of references.
*/
int increment();
/**
* Decrement number of references.
*
* @return number of references.
*/
int decrement();
/**
* Constructor of <code>ReferenceCountingLock</code>.
* After construction lock is free and reference count equals <code>1</code>.
*/
ReferenceCountingLock();
/**
* Destructor of <code>ReferenceCountingLock</code>.
*/
virtual ~ReferenceCountingLock();
/**
* Attempt to acquire lock.
*
* NOTE: Argument msecs is currently not supported due to
* Darwin OS not supporting pthread_mutex_timedlock. May be changed in the future.
*
* @param msecs the number of milleseconds to wait.
* An argument less than or equal to zero means not to wait at all.
*
* @return <code>true</code> if acquired, <code>false</code> otherwise.
* NOTE: currently this routine always returns true. Look above for explanation.
*
*/
bool acquire(epics::pvData::int64 msecs);
/**
* Release previously acquired lock.
*/
void release();
/**
* Increment number of references.
*
* @return number of references.
*/
int increment();
/**
* Decrement number of references.
*
* @return number of references.
*/
int decrement();
private:
int _references;
epics::pvData::Mutex _mutex;
epics::pvData::Mutex _countMutex;
int _references;
epics::pvData::Mutex _mutex;
epics::pvData::Mutex _countMutex;
};
}}
}
}
#endif /* REFERENCECOUNTINGLOCK_H */
+12 -10
View File
@@ -35,7 +35,8 @@
#include <shareLib.h>
namespace epics { namespace pvAccess {
namespace epics {
namespace pvAccess {
/**
* Class which implements UNIX style wildcards and tests to see
@@ -43,19 +44,19 @@ namespace epics { namespace pvAccess {
*/
class epicsShareClass Wildcard
{
public:
/**
public:
/**
* This function implements the UN*X wildcards.
* @param wildcard Wildcard to be used.
* @param test Value which we want to see if it matches the wildcard.
* @return 0 if wildcard does not match *test. 1 - if wildcard
* @return 0 if wildcard does not match *test. 1 - if wildcard
* matches test.
*/
static int wildcardfit (const char *wildcard, const char *test);
private:
private:
/**
* Scans a set of characters and returns 0 if the set mismatches at this
* position in the teststring and 1 if it is matching
@@ -66,7 +67,7 @@ class epicsShareClass Wildcard
* @return 0 if the set mismatches. 1 otherwise.
*/
static int set (const char **wildcard, const char **test);
/**
* Scans an asterisk.
* @param wildcard UNIX style wildcard to be used
@@ -76,7 +77,8 @@ class epicsShareClass Wildcard
static int asterisk (const char **wildcard, const char **test);
};
} }
}
}
#endif
+58 -57
View File
@@ -13,30 +13,30 @@ using namespace epics::pvData;
ReferenceCountingLock::ReferenceCountingLock(): _references(1)
{
/* pthread_mutexattr_t mutexAttribute;
int32 retval = pthread_mutexattr_init(&mutexAttribute);
if(retval != 0)
{
//string errMsg = "Error: pthread_mutexattr_init failed: " + string(strerror(retval));
assert(false);
}
retval = pthread_mutexattr_settype(&mutexAttribute, PTHREAD_MUTEX_RECURSIVE);
if(retval == 0)
{
retval = pthread_mutex_init(_mutex, &mutexAttribute);
if(retval != 0)
{
//string errMsg = "Error: pthread_mutex_init failed: " + string(strerror(retval));
assert(false);
}
}
else
{
//string errMsg = "Error: pthread_mutexattr_settype failed: " + string(strerror(retval));
assert(false);
}
/* pthread_mutexattr_t mutexAttribute;
int32 retval = pthread_mutexattr_init(&mutexAttribute);
if(retval != 0)
{
//string errMsg = "Error: pthread_mutexattr_init failed: " + string(strerror(retval));
assert(false);
}
retval = pthread_mutexattr_settype(&mutexAttribute, PTHREAD_MUTEX_RECURSIVE);
if(retval == 0)
{
retval = pthread_mutex_init(_mutex, &mutexAttribute);
if(retval != 0)
{
//string errMsg = "Error: pthread_mutex_init failed: " + string(strerror(retval));
assert(false);
}
}
else
{
//string errMsg = "Error: pthread_mutexattr_settype failed: " + string(strerror(retval));
assert(false);
}
pthread_mutexattr_destroy(&mutexAttribute);*/
pthread_mutexattr_destroy(&mutexAttribute);*/
}
ReferenceCountingLock::~ReferenceCountingLock()
@@ -46,54 +46,55 @@ ReferenceCountingLock::~ReferenceCountingLock()
bool ReferenceCountingLock::acquire(int64 /*msecs*/)
{
_mutex.lock();
return true;
/* struct timespec deltatime;
if(msecs > 0)
{
deltatime.tv_sec = msecs / 1000;
deltatime.tv_nsec = (msecs % 1000) * 1000;
}
else
{
deltatime.tv_sec = 0;
deltatime.tv_nsec = 0;
}
_mutex.lock();
return true;
/* struct timespec deltatime;
if(msecs > 0)
{
deltatime.tv_sec = msecs / 1000;
deltatime.tv_nsec = (msecs % 1000) * 1000;
}
else
{
deltatime.tv_sec = 0;
deltatime.tv_nsec = 0;
}
int32 retval = pthread_mutex_timedlock(_mutex, &deltatime);
if(retval == 0)
{
return true;
}
return false;
*/
int32 retval = pthread_mutex_timedlock(_mutex, &deltatime);
if(retval == 0)
{
return true;
}
return false;
*/
}
void ReferenceCountingLock::release()
{
_mutex.unlock();
/* int retval = pthread_mutex_unlock(_mutex);
if(retval != 0)
{
//string errMsg = "Error: pthread_mutex_unlock failed: " + string(strerror(retval));
//TODO do something?
}*/
_mutex.unlock();
/* int retval = pthread_mutex_unlock(_mutex);
if(retval != 0)
{
//string errMsg = "Error: pthread_mutex_unlock failed: " + string(strerror(retval));
//TODO do something?
}*/
}
// TODO use atomic primitive impl.
int ReferenceCountingLock::increment()
{
Lock guard(_countMutex);
++_references;
return _references;
Lock guard(_countMutex);
++_references;
return _references;
}
int ReferenceCountingLock::decrement()
{
Lock guard(_countMutex);
--_references;
return _references;
Lock guard(_countMutex);
--_references;
return _references;
}
}}
}
}
+91 -91
View File
@@ -38,131 +38,131 @@ using namespace epics::pvAccess;
int
Wildcard::wildcardfit (const char *wildcard, const char *test)
{
int fit = 1;
for (; ('\000' != *wildcard) && (1 == fit) && ('\000' != *test); wildcard++)
int fit = 1;
for (; ('\000' != *wildcard) && (1 == fit) && ('\000' != *test); wildcard++)
{
switch (*wildcard)
switch (*wildcard)
{
case '[':
wildcard++; /* leave out the opening square bracket */
fit = set (&wildcard, &test);
/* we don't need to decrement the wildcard as in case */
/* of asterisk because the closing ] is still there */
break;
wildcard++; /* leave out the opening square bracket */
fit = set (&wildcard, &test);
/* we don't need to decrement the wildcard as in case */
/* of asterisk because the closing ] is still there */
break;
case '?':
test++;
break;
test++;
break;
case '*':
fit = asterisk (&wildcard, &test);
/* the asterisk was skipped by asterisk() but the loop will */
/* increment by itself. So we have to decrement */
wildcard--;
break;
fit = asterisk (&wildcard, &test);
/* the asterisk was skipped by asterisk() but the loop will */
/* increment by itself. So we have to decrement */
wildcard--;
break;
default:
fit = (int) (*wildcard == *test);
test++;
fit = (int) (*wildcard == *test);
test++;
}
}
while ((*wildcard == '*') && (1 == fit))
/* here the teststring is empty otherwise you cannot */
/* leave the previous loop */
wildcard++;
return (int) ((1 == fit) && ('\0' == *test) && ('\0' == *wildcard));
while ((*wildcard == '*') && (1 == fit))
/* here the teststring is empty otherwise you cannot */
/* leave the previous loop */
wildcard++;
return (int) ((1 == fit) && ('\0' == *test) && ('\0' == *wildcard));
}
int
Wildcard::set (const char **wildcard, const char **test)
{
int fit = 0;
int negation = 0;
int at_beginning = 1;
int fit = 0;
int negation = 0;
int at_beginning = 1;
if ('!' == **wildcard)
if ('!' == **wildcard)
{
negation = 1;
(*wildcard)++;
negation = 1;
(*wildcard)++;
}
while ((']' != **wildcard) || (1 == at_beginning))
while ((']' != **wildcard) || (1 == at_beginning))
{
if (0 == fit)
if (0 == fit)
{
if (('-' == **wildcard)
&& ((*(*wildcard - 1)) < (*(*wildcard + 1)))
&& (']' != *(*wildcard + 1))
&& (0 == at_beginning))
if (('-' == **wildcard)
&& ((*(*wildcard - 1)) < (*(*wildcard + 1)))
&& (']' != *(*wildcard + 1))
&& (0 == at_beginning))
{
if (((**test) >= (*(*wildcard - 1)))
&& ((**test) <= (*(*wildcard + 1))))
if (((**test) >= (*(*wildcard - 1)))
&& ((**test) <= (*(*wildcard + 1))))
{
fit = 1;
(*wildcard)++;
fit = 1;
(*wildcard)++;
}
}
else if ((**wildcard) == (**test))
else if ((**wildcard) == (**test))
{
fit = 1;
fit = 1;
}
}
(*wildcard)++;
at_beginning = 0;
(*wildcard)++;
at_beginning = 0;
}
if (1 == negation)
/* change from zero to one and vice versa */
fit = 1 - fit;
if (1 == fit)
(*test)++;
if (1 == negation)
/* change from zero to one and vice versa */
fit = 1 - fit;
if (1 == fit)
(*test)++;
return (fit);
return (fit);
}
int
Wildcard::asterisk (const char **wildcard, const char **test)
{
/* Warning: uses multiple returns */
int fit = 1;
/* Warning: uses multiple returns */
int fit = 1;
/* erase the leading asterisk */
(*wildcard)++;
while (('\000' != (**test))
&& (('?' == **wildcard)
|| ('*' == **wildcard)))
{
if ('?' == **wildcard)
(*test)++;
(*wildcard)++;
}
/* Now it could be that test is empty and wildcard contains */
/* aterisks. Then we delete them to get a proper state */
while ('*' == (**wildcard))
/* erase the leading asterisk */
(*wildcard)++;
if (('\0' == (**test)) && ('\0' != (**wildcard)))
return (fit = 0);
if (('\0' == (**test)) && ('\0' == (**wildcard)))
return (fit = 1);
else
while (('\000' != (**test))
&& (('?' == **wildcard)
|| ('*' == **wildcard)))
{
/* Neither test nor wildcard are empty! */
/* the first character of wildcard isn't in [*?] */
if (0 == wildcardfit(*wildcard, (*test)))
{
do
{
(*test)++;
/* skip as much characters as possible in the teststring */
/* stop if a character match occurs */
while (((**wildcard) != (**test))
&& ('[' != (**wildcard))
&& ('\0' != (**test)))
(*test)++;
}
while ((('\0' != **test))?
(0 == wildcardfit (*wildcard, (*test)))
: (0 != (fit = 0)));
}
if (('\0' == **test) && ('\0' == **wildcard))
fit = 1;
return (fit);
if ('?' == **wildcard)
(*test)++;
(*wildcard)++;
}
/* Now it could be that test is empty and wildcard contains */
/* aterisks. Then we delete them to get a proper state */
while ('*' == (**wildcard))
(*wildcard)++;
if (('\0' == (**test)) && ('\0' != (**wildcard)))
return (fit = 0);
if (('\0' == (**test)) && ('\0' == (**wildcard)))
return (fit = 1);
else
{
/* Neither test nor wildcard are empty! */
/* the first character of wildcard isn't in [*?] */
if (0 == wildcardfit(*wildcard, (*test)))
{
do
{
(*test)++;
/* skip as much characters as possible in the teststring */
/* stop if a character match occurs */
while (((**wildcard) != (**test))
&& ('[' != (**wildcard))
&& ('\0' != (**test)))
(*test)++;
}
while ((('\0' != **test))?
(0 == wildcardfit (*wildcard, (*test)))
: (0 != (fit = 0)));
}
if (('\0' == **test) && ('\0' == **wildcard))
fit = 1;
return (fit);
}
}