Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
301 ashish 1
//  Copyright (c) 2007-2008 Facebook
2
//
3
//  Licensed under the Apache License, Version 2.0 (the "License");
4
//  you may not use this file except in compliance with the License.
5
//  You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//  Unless required by applicable law or agreed to in writing, software
10
//  distributed under the License is distributed on an "AS IS" BASIS,
11
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//  See the License for the specific language governing permissions and
13
//  limitations under the License.
14
//
15
// See accompanying file LICENSE or visit the Scribe site at:
16
// http://developers.facebook.com/scribe/
17
//
18
// @author Bobby Johnson
19
// @author Jason Sobel
20
 
21
#include "common.h"
22
#include "conf.h"
23
 
24
using namespace boost;
25
using namespace std;
26
 
27
StoreConf::StoreConf() {
28
}
29
 
30
StoreConf::~StoreConf() {
31
}
32
 
33
bool StoreConf::getStore(const std::string& storeName, pStoreConf& _return) {
34
  store_conf_map_t::iterator iter = stores.find(storeName);
35
  if (iter != stores.end()) {
36
    _return = iter->second;
37
    return true;
38
  } else {
39
    return false;
40
  }
41
}
42
 
43
void StoreConf::getAllStores(std::vector<pStoreConf>& _return) {
44
  for (store_conf_map_t::iterator iter = stores.begin(); iter != stores.end(); ++iter) {
45
    _return.push_back(iter->second);
46
  }
47
}
48
 
49
bool StoreConf::getInt(const std::string& intName, long int& _return) {
50
  string str;
51
  if (getString(intName, str)) {
52
    _return = strtol(str.c_str(), NULL, 0);
53
    return true;
54
  } else {
55
    return false;
56
  }
57
}
58
 
59
bool StoreConf::getUnsigned(const std::string& intName, unsigned long int& _return) {
60
  string str;
61
  if (getString(intName, str)) {
62
    _return = strtoul(str.c_str(), NULL, 0);
63
    return true;
64
  } else {
65
    return false;
66
  }
67
}
68
 
69
bool StoreConf::getString(const std::string& stringName, std::string& _return) {
70
  string_map_t::iterator iter = values.find(stringName);
71
  if (iter != values.end()) {
72
    _return = iter->second;
73
    return true;
74
  } else {
75
    return false;
76
  }
77
}
78
 
79
void StoreConf::setString(const std::string& stringName, const std::string& value) {
80
  values[stringName] = value;
81
}
82
 
83
void StoreConf::setUnsigned(const std::string& stringName, unsigned long value) {
84
  ostringstream oss;
85
  oss << value;
86
  setString(stringName, oss.str());
87
}
88
 
89
// reads and parses the config data
90
void StoreConf::parseConfig(const std::string& filename) {
91
 
92
  queue<string> config_strings;
93
 
94
  if (readConfFile(filename, config_strings)) {
95
    LOG_OPER("got configuration data from file <%s>", filename.c_str());
96
  } else {
97
    std::ostringstream msg;
98
    msg << "Failed to open config file <" << filename << ">";
99
    throw std::runtime_error(msg.str());
100
  }
101
 
102
  parseStore(config_strings, this);
103
}
104
 
105
// Side-effects:  - removes items from raw_config and adds items to parsed_config
106
//
107
// Returns true if a valid entry was found
108
bool StoreConf::parseStore(queue<string>& raw_config, /*out*/ StoreConf* parsed_config) {
109
 
110
  int store_index = 0; // used to give things named "store" different names
111
 
112
  string line;
113
  while (!raw_config.empty()) {
114
 
115
    line = raw_config.front();
116
    raw_config.pop();
117
 
118
    // remove leading and trailing whitespace
119
    line = trimString(line);
120
 
121
    // remove comment
122
    size_t comment = line.find_first_of('#');
123
    if (comment != string::npos) {
124
      line.erase(comment);
125
    }
126
 
127
    int length = line.size();
128
    if (0 >= length) {
129
      continue;
130
    }
131
    if (line[0] == '<') {
132
 
133
      if (length > 1 && line[1] == '/') {
134
        // This is the end of the current store
135
        return true;
136
      }
137
 
138
      // This is the start of a new store
139
      string::size_type pos = line.find('>');
140
      if (pos == string::npos) {
141
        LOG_OPER("Bad config - line %s has a < but not a >", line.c_str());
142
        continue;
143
      }
144
      string store_name = line.substr(1, pos - 1);
145
 
146
      pStoreConf new_store(new StoreConf);
147
      if (parseStore(raw_config, new_store.get())) {
148
        if (0 == store_name.compare("store")) {
149
          // This is a special case for the top-level stores. They share
150
          // the same name, so we append an index to put them in the map
151
          std::ostringstream oss;
152
          oss << store_index;
153
          store_name += oss.str();
154
          ++store_index;
155
        }
156
        if (parsed_config->stores.find(store_name) != parsed_config->stores.end()) {
157
          LOG_OPER("Bad config - duplicate store name %s", store_name.c_str());
158
        }
159
        parsed_config->stores[store_name] = new_store;
160
      }
161
    } else {
162
      string::size_type eq = line.find('=');
163
      if (eq == string::npos) {
164
        LOG_OPER("Bad config - line %s is missing an =", line.c_str());
165
      } else {
166
        string arg = line.substr(0, eq);
167
        string val = line.substr(eq + 1, string::npos);
168
 
169
        // remove leading and trailing whitespace
170
        arg = trimString(arg);
171
        val = trimString(val);
172
 
173
        if (parsed_config->values.find(arg) != parsed_config->values.end()) {
174
          LOG_OPER("Bad config - duplicate key %s", arg.c_str());
175
        }
176
        parsed_config->values[arg] = val;
177
      }
178
    }
179
  }
180
  return true;
181
}
182
 
183
// trims leading and trailing whitespace from a string
184
string StoreConf::trimString(const string& str) {
185
  string whitespace = " \t";
186
  size_t start      = str.find_first_not_of(whitespace);
187
  size_t end        = str.find_last_not_of(whitespace);
188
 
189
  if (start != string::npos) {
190
    return str.substr(start, end - start + 1);
191
  } else {
192
    return "";
193
  }
194
}
195
 
196
// reads every line from the file and pushes then onto _return
197
// returns false on error
198
bool StoreConf::readConfFile(const string& filename, queue<string>& _return) {
199
  std::string line;
200
  std::ifstream config_file;
201
 
202
  config_file.open(filename.c_str());
203
  if (!config_file.good()) {
204
    return false;
205
  }
206
 
207
  while (std::getline(config_file, line)) {
208
    _return.push(line);
209
  }
210
 
211
  config_file.close();
212
  return true;
213
}