~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/program_options/config_file.h

  • Committer: Lee Bieber
  • Date: 2010-11-15 04:50:59 UTC
  • mfrom: (1931.1.2 build)
  • Revision ID: kalebral@gmail.com-20101115045059-syjxk4sjrwmkz2sf
Merge Andrew - fix bug 674381: global_status test failure
Merge Monty - fix bug 669635: Boolean options in config file require a value while command line does not 
Merge Monty- fix bug #669707: Crash from boost::condition_variable assert fail when datadir is not full path

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Copyright (c) 2002-2004 Vladimir Prus.
 
3
 * Copyright (c) 2010 Monty Taylor
3
4
 *
4
5
 * Distributed under the Boost Software License, Version 1.0.
5
6
 * (See accompanying file LICENSE_1_0.txt or copy at
28
29
namespace program_options
29
30
{
30
31
 
 
32
typedef std::pair<std::string, std::string> option_result_pair;
 
33
std::string parse_suffix(const std::string& arg_val);
 
34
option_result_pair parse_size_suffixes(std::string s);
 
35
option_result_pair parse_size_arg(std::string s);
 
36
 
 
37
std::string parse_suffix(const std::string& arg_val)
 
38
{
 
39
  try
 
40
  {
 
41
    size_t size_suffix_pos= arg_val.find_last_of("kmgKMG");
 
42
    if (size_suffix_pos == arg_val.size()-1)
 
43
    {
 
44
      char suffix= arg_val[size_suffix_pos];
 
45
      std::string size_val(arg_val.substr(0, size_suffix_pos));
 
46
 
 
47
      uint64_t base_size= boost::lexical_cast<uint64_t>(size_val);
 
48
      uint64_t new_size= 0;
 
49
 
 
50
      switch (suffix)
 
51
      {
 
52
      case 'K':
 
53
      case 'k':
 
54
        new_size= base_size * 1024;
 
55
        break;
 
56
      case 'M':
 
57
      case 'm':
 
58
        new_size= base_size * 1024 * 1024;
 
59
        break;
 
60
      case 'G':
 
61
      case 'g':
 
62
        new_size= base_size * 1024 * 1024 * 1024;
 
63
        break;
 
64
      }
 
65
      return boost::lexical_cast<std::string>(new_size);
 
66
    }
 
67
  }
 
68
  catch (...)
 
69
  { }
 
70
 
 
71
  return arg_val;
 
72
}
 
73
 
 
74
option_result_pair parse_size_suffixes(std::string s)
 
75
{
 
76
  size_t equal_pos= s.find("=");
 
77
  if (equal_pos != std::string::npos)
 
78
  {
 
79
    std::string arg_key(s.substr(0, equal_pos));
 
80
    std::string arg_val(parse_suffix(s.substr(equal_pos+1)));
 
81
 
 
82
    if (arg_val != s.substr(equal_pos+1))
 
83
    {
 
84
      return std::make_pair(arg_key, arg_val);
 
85
    }
 
86
  }
 
87
 
 
88
  return std::make_pair(std::string(""), std::string(""));
 
89
}
 
90
 
 
91
option_result_pair parse_size_arg(std::string s)
 
92
{
 
93
  if (s.find("--") == 0)
 
94
  {
 
95
    return parse_size_suffixes(s.substr(2));
 
96
  }
 
97
  return make_pair(std::string(""), std::string(""));
 
98
}
 
99
 
31
100
class invalid_syntax :
32
101
  public boost::program_options::error
33
102
{
34
103
public:
35
 
  enum kind_t {
 
104
  enum kind_t
 
105
  {
36
106
    long_not_allowed = 30,
37
107
    long_adjacent_not_allowed,
38
108
    short_adjacent_not_allowed,
106
176
 
107
177
invalid_syntax::invalid_syntax(const std::string& in_tokens,
108
178
                               invalid_syntax::kind_t in_kind) :
109
 
 boost::program_options::error(error_message(in_kind).append(" in '").append(in_tokens).append("'"))
110
 
, m_tokens(in_tokens)
111
 
  , m_kind(in_kind)
112
 
{}
 
179
  boost::program_options::error(error_message(in_kind).append(" in '").append(in_tokens).append("'")),
 
180
  m_tokens(in_tokens),
 
181
  m_kind(in_kind)
 
182
{ }
113
183
 
114
184
namespace detail
115
185
{
185
255
 
186
256
      if (!s.empty()) {
187
257
        // Handle section name
188
 
        if (*s.begin() == '[' && *s.rbegin() == ']') {
 
258
        if (*s.begin() == '[' && *s.rbegin() == ']')
 
259
        {
189
260
          m_prefix = s.substr(1, s.size()-2);
190
261
          if (*m_prefix.rbegin() != '.')
191
262
            m_prefix += '.';
192
263
        }
193
 
        else if ((n = s.find('=')) != std::string::npos) {
194
 
 
195
 
          std::string name = m_prefix + boost::trim_copy(s.substr(0, n));
196
 
          std::string option_value = boost::trim_copy(s.substr(n+1));
 
264
        else
 
265
        {
 
266
          
 
267
          std::string name;
 
268
          std::string option_value("true");
 
269
 
 
270
          if ((n = s.find('=')) != std::string::npos)
 
271
          {
 
272
 
 
273
            name = m_prefix + boost::trim_copy(s.substr(0, n));
 
274
            option_value = boost::trim_copy(parse_suffix(s.substr(n+1)));
 
275
 
 
276
          }
 
277
          else
 
278
          {
 
279
            name = m_prefix + boost::trim_copy(s);
 
280
          }
197
281
 
198
282
          bool registered = allowed_option(name);
199
283
          if (!registered && !m_allow_unregistered)
209
293
          this->value().original_tokens.push_back(option_value);
210
294
          break;
211
295
 
212
 
        } else {
213
 
          boost::throw_exception(invalid_syntax(s, invalid_syntax::unrecognized_line));
214
296
        }
215
297
      }
216
298
    }
236
318
  {
237
319
    std::string s(name);
238
320
    assert(!s.empty());
239
 
    if (*s.rbegin() == '*') {
 
321
    if (*s.rbegin() == '*')
 
322
    {
240
323
      s.resize(s.size()-1);
241
324
      bool bad_prefixes(false);
242
325
      // If 's' is a prefix of one of allowed suffix, then
244
327
      // If some element is prefix of 's', then lower_bound will
245
328
      // return the next element.
246
329
      std::set<std::string>::iterator i = allowed_prefixes.lower_bound(s);
247
 
      if (i != allowed_prefixes.end()) {
 
330
      if (i != allowed_prefixes.end())
 
331
      {
248
332
        if (i->find(s) == 0)
249
333
          bad_prefixes = true;                    
250
334
      }
251
 
      if (i != allowed_prefixes.begin()) {
 
335
      if (i != allowed_prefixes.begin())
 
336
      {
252
337
        --i;
253
338
        if (s.find(*i) == 0)
254
339
          bad_prefixes = true;
338
423
bool
339
424
basic_config_file_iterator<charT>::getline(std::string& s)
340
425
{
341
 
  if (std::getline(*is, s)) {
 
426
  if (std::getline(*is, s))
 
427
  {
342
428
    return true;
343
 
  } else {
 
429
  }
 
430
  else
 
431
  {
344
432
    return false;
345
433
  }
346
434
}
365
453
    const boost::program_options::option_description& d= *options[i];
366
454
 
367
455
    if (d.long_name().empty())
368
 
      boost::throw_exception(
369
 
                             boost::program_options::error("long name required for config file"));
 
456
      boost::throw_exception(boost::program_options::error("long name required for config file"));
370
457
 
371
458
    allowed_options.insert(d.long_name());
372
459
  }
373
460
 
374
461
  // Parser return char strings
375
462
  boost::program_options::parsed_options result(&desc);        
376
 
  std::copy(detail::basic_config_file_iterator<charT>(
377
 
                                                      is, allowed_options, allow_unregistered), 
 
463
  std::copy(detail::basic_config_file_iterator<charT>(is,
 
464
                                                      allowed_options,
 
465
                                                      allow_unregistered), 
378
466
       detail::basic_config_file_iterator<charT>(), 
379
467
       std::back_inserter(result.options));
380
468
  // Convert char strings into desired type.