#ifdef _MSC_VER
#include "stdafx.h"
#else
#include "config.h"
#endif
#include "Settings.h"
#include <cstring>
namespace FIX {
bool isComment(const std::string &line) {
if (line.size() == 0) {
return false;
}
return line[0] == '#';
}
bool isSection(const std::string &line) {
if (line.size() == 0) {
return false;
}
return line[0] == '[' && line[line.size() - 1] == ']';
}
std::string splitSection(const std::string &line) { return string_strip(std::string(line, 1, line.size() - 2)); }
bool isKeyValue(const std::string &line) { return line.find('=') != std::string::npos; }
std::pair<std::string, std::string> splitKeyValue(const std::string &line) {
size_t equals = line.find('=');
std::string key = std::string(line, 0, equals);
std::string value = std::string(line, equals + 1, std::string::npos);
return std::pair<std::string, std::string>(key, value);
}
std::string resolveEnvVars(const std::string &str) {
std::string resultStr;
size_t actPos = 0;
size_t sourceLen = str.length();
while (actPos < sourceLen) {
char c = str[actPos++];
if (actPos < sourceLen) {
if (c == '\\') {
c = str[actPos++];
switch (c) {
case 't':
resultStr.append(1, '\t');
break;
case 'r':
resultStr.append(1, '\r');
break;
case 'n':
resultStr.append(1, '\n');
break;
default:
resultStr.append(1, c);
break;
}
continue;
}
if (c == '$') {
bool inBraces = false;
c = str[actPos++];
if ((c == '(') || (c == '{')) {
c = str[actPos++];
inBraces = true;
}
if (actPos >= sourceLen) {
break;
}
std::string varName;
while ((actPos <= sourceLen)) {
varName.append(1, c); c = str[actPos++];
if (std::strchr(" /:;,.=\"'?#+*()[]{}$&%\t\n", c)) {
break;
}
}
if (inBraces && (actPos <= sourceLen) && ((c == ')') || (c == '}')))
;
else {
--actPos;
}
const char *varValue = 0;
if (!varName.empty() && (0 != (varValue = getenv(varName.c_str())))) {
resultStr.append(varValue);
}
continue;
}
}
resultStr.append(1, c);
}
return resultStr;
}
std::istream &operator>>(std::istream &stream, Settings &s) {
char buffer[1024];
std::string line;
Settings::Sections::iterator section = s.m_sections.end();
;
while (stream.getline(buffer, sizeof(buffer))) {
line = string_strip(buffer);
if (isComment(line)) {
continue;
} else if (isSection(line)) {
section = s.m_sections.insert(s.m_sections.end(), Dictionary(splitSection(line)));
} else if (isKeyValue(line)) {
std::pair<std::string, std::string> keyValue = splitKeyValue(line);
if (section == s.m_sections.end()) {
continue;
}
(*section).setString(keyValue.first, s.m_resolveEnvVars ? resolveEnvVars(keyValue.second) : keyValue.second);
}
}
return stream;
}
Settings::Sections Settings::get(const std::string &name) const {
Sections sections;
for (Sections::size_type i = 0; i < m_sections.size(); ++i) {
if (m_sections[i].getName() == name) {
sections.push_back(m_sections[i]);
}
}
return sections;
}
}