~ubuntu-branches/ubuntu/saucy/resiprocate/saucy-proposed

« back to all changes in this revision

Viewing changes to rutil/ConfigParse.cxx

  • Committer: Package Import Robot
  • Author(s): Daniel Pocock
  • Date: 2012-05-17 19:29:59 UTC
  • Revision ID: package-import@ubuntu.com-20120517192959-vv00m77isztdy64q
Tags: upstream-1.8.2
ImportĀ upstreamĀ versionĀ 1.8.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <iostream>
 
2
#include <fstream>
 
3
#include <iterator>
 
4
#include <stdexcept>
 
5
 
 
6
#include "rutil/ConfigParse.hxx"
 
7
#include "rutil/Log.hxx"
 
8
#include "rutil/Logger.hxx"
 
9
#include "rutil/ParseBuffer.hxx"
 
10
#include "rutil/WinLeakCheck.hxx"
 
11
 
 
12
using namespace resip;
 
13
using namespace std;
 
14
 
 
15
#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
 
16
 
 
17
namespace resip
 
18
{
 
19
 
 
20
ConfigParse::ConfigParse(int argc, char** argv, const resip::Data& defaultConfigFilename)
 
21
{
 
22
   parseCommandLine(argc, argv);  // will fill in mCmdLineConfigFilename if present
 
23
   if(mCmdLineConfigFilename.empty())
 
24
   {
 
25
      parseConfigFile(defaultConfigFilename);
 
26
   }
 
27
   else
 
28
   {
 
29
      parseConfigFile(mCmdLineConfigFilename);
 
30
   }
 
31
}
 
32
 
 
33
ConfigParse::ConfigParse()
 
34
{
 
35
}
 
36
 
 
37
ConfigParse::~ConfigParse()
 
38
{
 
39
}
 
40
 
 
41
bool 
 
42
ConfigParse::getConfigValue(const resip::Data& name, resip::Data &value)
 
43
{
 
44
   Data lowerName(name);  lowerName.lowercase();
 
45
   ConfigValuesMap::iterator it = mConfigValues.find(lowerName);
 
46
   if(it != mConfigValues.end())
 
47
   {
 
48
      value = it->second;
 
49
      return true;
 
50
   }
 
51
   // Not found
 
52
   return false;
 
53
}
 
54
 
 
55
Data 
 
56
ConfigParse::getConfigData(const resip::Data& name, const resip::Data& defaultValue, bool useDefaultIfEmpty)
 
57
{
 
58
   Data ret(defaultValue);
 
59
   if(getConfigValue(name, ret) && ret.empty() && useDefaultIfEmpty)
 
60
   {
 
61
      return defaultValue;
 
62
   }
 
63
   return ret;
 
64
}
 
65
 
 
66
bool 
 
67
ConfigParse::getConfigValue(const resip::Data& name, bool &value)
 
68
{
 
69
   Data lowerName(name);  lowerName.lowercase();
 
70
   ConfigValuesMap::iterator it = mConfigValues.find(lowerName);
 
71
   if(it != mConfigValues.end())
 
72
   {
 
73
      if(it->second == "1" || 
 
74
         isEqualNoCase(it->second, "true") || 
 
75
         isEqualNoCase(it->second, "on") || 
 
76
         isEqualNoCase(it->second, "enable"))
 
77
      {
 
78
         value = true;
 
79
         return true;
 
80
      }
 
81
      else if(it->second == "0" ||
 
82
              isEqualNoCase(it->second, "false") || 
 
83
              isEqualNoCase(it->second, "off") || 
 
84
              isEqualNoCase(it->second, "disable"))
 
85
      {
 
86
         value = false;
 
87
         return true;
 
88
      }
 
89
      cerr << "Invalid boolean setting:  " << name << " = " << it->second << ": Valid values are: 1,true,on,enable,0,false,off or disable" << endl;
 
90
      return false;
 
91
   }
 
92
   // Not found
 
93
   return false;
 
94
}
 
95
 
 
96
bool 
 
97
ConfigParse::getConfigBool(const resip::Data& name, bool defaultValue)
 
98
{
 
99
   bool ret = defaultValue;
 
100
   getConfigValue(name, ret);
 
101
   return ret;
 
102
}
 
103
 
 
104
bool 
 
105
ConfigParse::getConfigValue(const resip::Data& name, unsigned long &value)
 
106
{
 
107
   Data lowerName(name);  lowerName.lowercase();
 
108
   ConfigValuesMap::iterator it = mConfigValues.find(lowerName);
 
109
   if(it != mConfigValues.end())
 
110
   {
 
111
      value = it->second.convertUnsignedLong();
 
112
      return true;
 
113
   }
 
114
   // Not found
 
115
   return false;
 
116
}
 
117
 
 
118
unsigned long 
 
119
ConfigParse::getConfigUnsignedLong(const resip::Data& name, unsigned long defaultValue)
 
120
{
 
121
   unsigned long ret = defaultValue;
 
122
   getConfigValue(name, ret);
 
123
   return ret;
 
124
}
 
125
 
 
126
bool 
 
127
ConfigParse::getConfigValue(const resip::Data& name, int &value)
 
128
{
 
129
   Data lowerName(name);  lowerName.lowercase();
 
130
   ConfigValuesMap::iterator it = mConfigValues.find(lowerName);
 
131
   if(it != mConfigValues.end())
 
132
   {
 
133
      value = it->second.convertInt();
 
134
      return true;
 
135
   }
 
136
   // Not found
 
137
   return false;
 
138
}
 
139
 
 
140
 
 
141
int 
 
142
ConfigParse::getConfigInt(const resip::Data& name, int defaultValue)
 
143
{
 
144
   int ret = defaultValue;
 
145
   getConfigValue(name, ret);
 
146
   return ret;
 
147
}
 
148
 
 
149
bool
 
150
ConfigParse::getConfigValue(const resip::Data& name, unsigned short &value)
 
151
{
 
152
   Data lowerName(name);  lowerName.lowercase();
 
153
   ConfigValuesMap::iterator it = mConfigValues.find(lowerName);
 
154
   if(it != mConfigValues.end())
 
155
   {
 
156
      value = it->second.convertInt();
 
157
      return true;
 
158
   }
 
159
   // Not found
 
160
   return false;
 
161
}
 
162
 
 
163
 
 
164
unsigned short
 
165
ConfigParse::getConfigUnsignedShort(const resip::Data& name, int defaultValue)
 
166
{
 
167
   int ret = defaultValue;
 
168
   getConfigValue(name, ret);
 
169
   return ret;
 
170
}
 
171
 
 
172
bool 
 
173
ConfigParse::getConfigValue(const resip::Data& name, std::vector<resip::Data> &value)
 
174
{
 
175
   Data lowerName(name);  lowerName.lowercase();
 
176
   std::pair<ConfigValuesMap::iterator,ConfigValuesMap::iterator> valuesIts = mConfigValues.equal_range(lowerName);
 
177
   bool found = false;
 
178
   for (ConfigValuesMap::iterator it=valuesIts.first; it!=valuesIts.second; ++it)
 
179
   {
 
180
      found = true;
 
181
      ParseBuffer pb(it->second);
 
182
      Data item;
 
183
      while(!it->second.empty() && !pb.eof())
 
184
      {
 
185
         pb.skipWhitespace();
 
186
         const char *start = pb.position();
 
187
         pb.skipToOneOf(ParseBuffer::Whitespace, ",");  // allow white space 
 
188
         pb.data(item, start);
 
189
         value.push_back(item);
 
190
         if(!pb.eof())
 
191
         {
 
192
            pb.skipChar();
 
193
         }
 
194
      }
 
195
   }
 
196
 
 
197
   return found;
 
198
}
 
199
 
 
200
void 
 
201
ConfigParse::insertConfigValue(const resip::Data& name, const resip::Data& value)
 
202
{
 
203
   resip::Data lowerName(name);
 
204
   lowerName.lowercase();
 
205
   mConfigValues.insert(ConfigValuesMap::value_type(lowerName, value));
 
206
}
 
207
 
 
208
void 
 
209
ConfigParse::parseCommandLine(int argc, char** argv)
 
210
{
 
211
   int startingArgForNameValuePairs = 1;
 
212
   // First argument is the configuration filename - it is optional and is never proceeded with a - or /
 
213
#ifdef WIN32
 
214
   if(argc >= 2 && argv[1][0] != '-' && argv[1][0] != '/')
 
215
#else
 
216
   if(argc >= 2 && argv[1][0] != '-')
 
217
#endif
 
218
   {
 
219
      mCmdLineConfigFilename = argv[1];
 
220
      startingArgForNameValuePairs = 2;
 
221
   }
 
222
 
 
223
   // Loop through command line arguments and process them
 
224
   for(int i = startingArgForNameValuePairs; i < argc; i++)
 
225
   {
 
226
      Data argData(argv[i]);
 
227
 
 
228
      // Process all commandNames that don't take values
 
229
      if(isEqualNoCase(argData, "-?") || 
 
230
         isEqualNoCase(argData, "--?") ||
 
231
         isEqualNoCase(argData, "--help") ||
 
232
         isEqualNoCase(argData, "/?"))
 
233
      {
 
234
         printHelpText(argc, argv);
 
235
         exit(1);
 
236
      }
 
237
      else if(argData.at(0) == '-' || argData.at(0) == '/')
 
238
      {
 
239
         Data name;
 
240
         Data value;
 
241
         ParseBuffer pb(argData);
 
242
 
 
243
         try
 
244
         {
 
245
            pb.skipChars(Data::toBitset("-/"));  // Skip any leading -'s or /'s
 
246
            const char * anchor = pb.position();
 
247
            pb.skipToOneOf("=:");
 
248
            if(!pb.eof())
 
249
            {
 
250
               pb.data(name, anchor);
 
251
               pb.skipChar();
 
252
               anchor = pb.position();
 
253
               pb.skipToEnd();
 
254
               pb.data(value, anchor);
 
255
 
 
256
               //cout << "Command line Name='" << name << "' value='" << value << "'" << endl;
 
257
               insertConfigValue(name, value);
 
258
            }
 
259
            else
 
260
            {
 
261
               cerr << "Invalid command line parameters:"  << endl;
 
262
               cerr << " Name/Value pairs must contain an = or a : between the name and the value" << endl;
 
263
               exit(-1);
 
264
            }
 
265
         }
 
266
         catch(BaseException& ex)
 
267
         {
 
268
            cerr << "Invalid command line parameters:"  << endl;
 
269
            cerr << " Exception parsing Name/Value pairs: " << ex << endl;
 
270
            exit(-1);
 
271
         }
 
272
      }
 
273
      else
 
274
      {
 
275
         cerr << "Invalid command line parameters:"  << endl;
 
276
         cerr << " Name/Value pairs must be prefixed with either a -, --, or a /" << endl;
 
277
         exit(-1);
 
278
      }
 
279
   }
 
280
}
 
281
 
 
282
void
 
283
ConfigParse::parseConfigFile(const Data& filename)
 
284
{
 
285
   ifstream configFile(filename.c_str());
 
286
   
 
287
   if(!configFile)
 
288
   {
 
289
      throw Exception("Error opening/reading configuration file", __FILE__, __LINE__);
 
290
   }
 
291
 
 
292
   string sline;
 
293
   const char * anchor;
 
294
   while(getline(configFile, sline)) 
 
295
   {
 
296
      Data line(sline);
 
297
      Data name;
 
298
      Data value;
 
299
      ParseBuffer pb(line);
 
300
 
 
301
      pb.skipWhitespace();
 
302
      anchor = pb.position();
 
303
      if(pb.eof() || *anchor == '#') continue;  // if line is a comment or blank then skip it
 
304
 
 
305
      // Look for end of name
 
306
      pb.skipToOneOf("= \t");
 
307
      pb.data(name,anchor);
 
308
      if(*pb.position()!='=') 
 
309
      {
 
310
         pb.skipToChar('=');
 
311
      }
 
312
      pb.skipChar('=');
 
313
      pb.skipWhitespace();
 
314
      anchor = pb.position();
 
315
      if(!pb.eof())
 
316
      {
 
317
         pb.skipToOneOf("\r\n");
 
318
         pb.data(value, anchor);
 
319
      }
 
320
      //cout << "Config file Name='" << name << "' value='" << value << "'" << endl;
 
321
      insertConfigValue(name, value);
 
322
   }
 
323
}
 
324
 
 
325
EncodeStream& 
 
326
operator<<(EncodeStream& strm, const ConfigParse& config)
 
327
{
 
328
   ConfigParse::ConfigValuesMap::const_iterator it = config.mConfigValues.begin();
 
329
   for(; it != config.mConfigValues.end(); it++)
 
330
   {
 
331
      strm << it->first << " = " << it->second << endl;
 
332
   }
 
333
   return strm;
 
334
}
 
335
 
 
336
}
 
337
 
 
338
/* ====================================================================
 
339
 * The Vovida Software License, Version 1.0 
 
340
 * 
 
341
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
 
342
 * 
 
343
 * Redistribution and use in source and binary forms, with or without
 
344
 * modification, are permitted provided that the following conditions
 
345
 * are met:
 
346
 * 
 
347
 * 1. Redistributions of source code must retain the above copyright
 
348
 *    notice, this list of conditions and the following disclaimer.
 
349
 * 
 
350
 * 2. Redistributions in binary form must reproduce the above copyright
 
351
 *    notice, this list of conditions and the following disclaimer in
 
352
 *    the documentation and/or other materials provided with the
 
353
 *    distribution.
 
354
 * 
 
355
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
 
356
 *    and "Vovida Open Communication Application Library (VOCAL)" must
 
357
 *    not be used to endorse or promote products derived from this
 
358
 *    software without prior written permission. For written
 
359
 *    permission, please contact vocal@vovida.org.
 
360
 *
 
361
 * 4. Products derived from this software may not be called "VOCAL", nor
 
362
 *    may "VOCAL" appear in their name, without prior written
 
363
 *    permission of Vovida Networks, Inc.
 
364
 * 
 
365
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 
366
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
367
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
 
368
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
 
369
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
 
370
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 
371
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
372
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
373
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 
374
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
375
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 
376
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 
377
 * DAMAGE.
 
378
 * 
 
379
 * ====================================================================
 
380
 * 
 
381
 * This software consists of voluntary contributions made by Vovida
 
382
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
 
383
 * Inc.  For more information on Vovida Networks, Inc., please see
 
384
 * <http://www.vovida.org/>.
 
385
 *
 
386
 */