This is Unofficial EPICS BASE Doxygen Site
configuration.cpp
Go to the documentation of this file.
1 
7 #include <algorithm>
8 
9 #include <pv/epicsException.h>
10 #include <pv/typeCast.h>
11 
12 #include <osiSock.h>
13 #include <epicsStdlib.h>
14 
15 #define epicsExportSharedSymbols
16 #include <pv/configuration.h>
17 
18 #if defined(__GNUC__) && __GNUC__ < 3
19 #define OLDGCC
20 #define NO_STREAM_EXCEPTIONS
21 #endif
22 
23 namespace epics {
24 namespace pvAccess {
25 
26 using namespace epics::pvData;
27 using namespace std;
28 
30 
31 bool Configuration::getPropertyAsBoolean(const std::string &name, const bool defaultValue) const
32 {
33  string value = getPropertyAsString(name, defaultValue ? "1" : "0");
34  std::transform(value.begin(), value.end(), value.begin(), ::tolower);
35 
36  bool isTrue = (value == "1") || (value == "true") || (value == "yes");
37  if (isTrue)
38  return true;
39 
40  bool isFalse = (value == "0") || (value == "false") || (value == "no");
41  if (isFalse)
42  return false;
43 
44  // invalid value
45  return defaultValue;
46 }
47 
48 epics::pvData::int32 Configuration::getPropertyAsInteger(const std::string &name, const epics::pvData::int32 defaultValue) const
49 {
50  try {
51  return castUnsafe<epics::pvData::int32>(getPropertyAsString(name, ""));
52  } catch(std::runtime_error&) {
53  return defaultValue;
54  }
55 }
56 
57 float Configuration::getPropertyAsFloat(const std::string &name, const float defaultValue) const
58 {
59  try {
60  return castUnsafe<float>(getPropertyAsString(name, ""));
61  } catch(std::runtime_error&) {
62  return defaultValue;
63  }
64 }
65 
66 double Configuration::getPropertyAsDouble(const std::string &name, const double defaultValue) const
67 {
68  try {
69  return castUnsafe<double>(getPropertyAsString(name, ""));
70  } catch(std::runtime_error&) {
71  return defaultValue;
72  }
73 }
74 
75 std::string Configuration::getPropertyAsString(const std::string &name, const std::string &defaultValue) const
76 {
77  std::string val;
78  if(tryGetPropertyAsString(name, &val))
79  return val;
80  else
81  return defaultValue;
82 }
83 
84 bool Configuration::getPropertyAsAddress(const std::string& name, osiSockAddr* addr) const
85 {
86  unsigned short dftport=0;
87  if(addr->sa.sa_family==AF_INET)
88  dftport = ntohs(addr->ia.sin_port);
89 
90  std::string val(getPropertyAsString(name, ""));
91 
92  if(val.empty()) return false;
93 
94  memset(addr, 0, sizeof(*addr));
95  addr->ia.sin_family = AF_INET;
96  if(aToIPAddr(val.c_str(), dftport, &addr->ia))
97  return false;
98  return true;
99 }
100 
101 bool Configuration::hasProperty(const std::string &name) const
102 {
103  return tryGetPropertyAsString(name, NULL);
104 }
105 
106 bool ConfigurationMap::tryGetPropertyAsString(const std::string& name, std::string* val) const
107 {
108  properties_t::const_iterator it = properties.find(name);
109  if(it==properties.end())
110  return false;
111  if(val)
112  *val = it->second;
113  return true;
114 }
115 
116 void ConfigurationMap::addKeys(keys_t& names) const
117 {
118  for(properties_t::const_iterator it=properties.begin(); it!=properties.end(); ++it)
119  names.insert(it->first);
120 }
121 
122 static
123 const ENV_PARAM * findEnvConfigParam( const char * envVarName )
124 {
125  const ENV_PARAM **ppParam = env_param_list;
126 
127  /* Find a match with one of the EPICS env vars */
128  while (*ppParam) {
129  if ( strcmp( envVarName, (*ppParam)->name ) == 0 ) {
130  return *ppParam;
131  }
132  ppParam++;
133  }
134 
135  return 0;
136 }
137 
138 
139 bool ConfigurationEnviron::tryGetPropertyAsString(const std::string& name, std::string* val) const
140 {
141  const char *env = getenv(name.c_str());
142  if(!env) {
143  const ENV_PARAM *pParam = findEnvConfigParam( name.c_str() );
144  if ( pParam )
145  env = pParam->pdflt;
146  }
147  if(!env || !*env)
148  return false;
149  if(val)
150  *val = env;
151  return true;
152 }
153 
154 bool ConfigurationStack::tryGetPropertyAsString(const std::string& name, std::string* val) const
155 {
156  for(confs_t::const_reverse_iterator it = confs.rbegin(), end = confs.rend();
157  it!=end; ++it)
158  {
159  Configuration& conf = **it;
160  if(conf.tryGetPropertyAsString(name, val))
161  return true;
162  }
163  return false;
164 }
165 
166 void ConfigurationStack::addKeys(keys_t& names) const
167 {
168  for(confs_t::const_iterator it=confs.begin(); it!=confs.end(); ++it)
169  (*it)->addKeys(names);
170 }
171 
173 
175 {
176  Configuration::shared_pointer env(new ConfigurationEnviron);
177  stack->push_back(env);
178  return *this;
179 }
180 
182 {
183  Configuration::shared_pointer env(new ConfigurationMap(mymap));
184  stack->push_back(env);
185  mymap.clear();
186  return *this;
187 }
188 
190 ConfigurationBuilder::push_config(const Configuration::shared_pointer& conf)
191 {
192  stack->push_back(conf);
193  return *this;
194 }
195 
197 ConfigurationBuilder::_add(const std::string& name, const std::string& val)
198 {
199  if(name.find_first_of(" \t\r\n")!=name.npos)
200  THROW_EXCEPTION2(std::invalid_argument, "Key name may not contain whitespace");
201  mymap[name] = val;
202  return *this;
203 }
204 
205 Configuration::shared_pointer ConfigurationBuilder::build()
206 {
207  if(!mymap.empty())
208  THROW_EXCEPTION2(std::logic_error, "Missing call to .push_map()");
209  if(stack->size()==0) {
210  return Configuration::shared_pointer(new ConfigurationMap); // empty map
211  } else if(stack->size()==1) {
212  return stack->pop_back();
213  } else {
214  return stack;
215  }
216 }
217 
218 void ConfigurationProviderImpl::registerConfiguration(const string &name, Configuration::shared_pointer const & configuration)
219 {
220  Lock guard(_mutex);
221  std::map<std::string,Configuration::shared_pointer>::iterator configsIter = _configs.find(name);
222  if(configsIter != _configs.end())
223  {
224  string msg = "configuration with name " + name + " already registered";
226  }
227  _configs[name] = configuration;
228 }
229 
230 Configuration::shared_pointer ConfigurationProviderImpl::getConfiguration(const string &name)
231 {
232  Lock guard(_mutex);
233  std::map<std::string,Configuration::shared_pointer>::iterator configsIter = _configs.find(name);
234  if(configsIter != _configs.end())
235  {
236  return configsIter->second;
237  }
238  Configuration::shared_pointer env(new ConfigurationEnviron); // default to environment only
239  _configs[name] = env; // ensure that a later attempt to define this config will fail
240  return env;
241 }
242 
243 ConfigurationProvider::shared_pointer configurationProvider;
245 
246 ConfigurationProvider::shared_pointer ConfigurationFactory::getProvider()
247 {
248  Lock guard(conf_factory_mutex);
249  if(configurationProvider.get() == NULL)
250  {
251  configurationProvider.reset(new ConfigurationProviderImpl());
252  Configuration::shared_pointer systemConfig(new ConfigurationEnviron);
253  configurationProvider->registerConfiguration("system", systemConfig);
254  }
255  return configurationProvider;
256 }
257 
258 }
259 }
epics::pvData::int32 getPropertyAsInteger(const std::string &name, const epics::pvData::int32 defaultValue) const
Configuration::shared_pointer build()
Definition: link.h:174
LIBCOM_API int epicsStdCall aToIPAddr(const char *pAddrString, unsigned short defaultPort, struct sockaddr_in *pIP)
Definition: aToIPAddr.c:78
static ConfigurationProvider::shared_pointer getProvider()
#define THROW_EXCEPTION2(TYPE, MSG)
struct sockaddr sa
Definition: osiSock.h:158
Lookup configuration strings from the process environment.
double getPropertyAsDouble(const std::string &name, const double defaultValue) const
Configuration::shared_pointer getConfiguration(const std::string &name)
struct sockaddr_in ia
Definition: osiSock.h:157
Definition: memory.hpp:41
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
A lock for multithreading.
Definition: lock.h:36
#define NULL
Definition: catime.c:38
std::set< std::string > keys_t
char * pdflt
Default value.
Definition: envDefs.h:43
A structure to hold a single environment parameter.
Definition: envDefs.h:41
ConfigurationProvider::shared_pointer configurationProvider
virtual void addKeys(keys_t &) const
pvData
Definition: monitor.h:428
std::string getPropertyAsString(const std::string &name, const std::string &defaultValue) const
bool getPropertyAsBoolean(const std::string &name, const bool defaultValue) const
float getPropertyAsFloat(const std::string &name, const float defaultValue) const
bool getPropertyAsAddress(const std::string &name, osiSockAddr *addr) const
#define THROW_BASE_EXCEPTION(msg)
Lookup configuration strings from an in memory store.
virtual bool tryGetPropertyAsString(const std::string &name, std::string *val) const =0
epicsMutex Mutex
Definition: lock.h:28
bool hasProperty(const std::string &name) const
LIBCOM_API const ENV_PARAM * env_param_list[]
ConfigurationBuilder & push_config(const Configuration::shared_pointer &)
int32_t int32
Definition: pvType.h:83
void registerConfiguration(const std::string &name, Configuration::shared_pointer const &configuration)