159 lines
5.3 KiB
C++
159 lines
5.3 KiB
C++
/*
|
|
* Properties.cpp
|
|
*
|
|
* Copyright 2002, Log4cpp Project. All rights reserved.
|
|
*
|
|
* See the COPYING file for the terms of usage and distribution.
|
|
*/
|
|
|
|
#include "Properties.hh"
|
|
#include <cstdlib>
|
|
#include "StringUtil.hh"
|
|
|
|
namespace log4cpp {
|
|
|
|
Properties::Properties() {
|
|
}
|
|
|
|
Properties::~Properties() {
|
|
}
|
|
|
|
void Properties::load(std::istream& in) {
|
|
clear();
|
|
|
|
std::string fullLine, command;
|
|
std::string leftSide, rightSide;
|
|
char line[256];
|
|
std::string::size_type length;
|
|
bool partiallyRead(false); // fix for bug#137, for strings longer than 256 chars
|
|
|
|
while (in) {
|
|
if (in.getline(line, 256) || !in.bad()) {
|
|
// either string is read fully or only partially (logical but not read/write error)
|
|
if (partiallyRead)
|
|
fullLine.append(line);
|
|
else
|
|
fullLine = line;
|
|
partiallyRead = (in.fail() && !in.bad());
|
|
if (partiallyRead && !in.eof()) {
|
|
in.clear(in.rdstate() & ~std::ios::failbit);
|
|
continue; // to get full line
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
/* if the line contains a # then it is a comment
|
|
if we find it anywhere other than the beginning, then we assume
|
|
there is a command on that line, and it we don't find it at all
|
|
we assume there is a command on the line (we test for valid
|
|
command later) if neither is true, we continue with the next line
|
|
*/
|
|
length = fullLine.find('#');
|
|
if (length == std::string::npos) {
|
|
command = fullLine;
|
|
} else if (length > 0) {
|
|
command = fullLine.substr(0, length);
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
// check the command and handle it
|
|
length = command.find('=');
|
|
if (length != std::string::npos) {
|
|
leftSide = StringUtil::trim(command.substr(0, length));
|
|
rightSide = StringUtil::trim(command.substr(length + 1, command.size() - length));
|
|
_substituteVariables(rightSide);
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
/* handle the command by determining what object the left side
|
|
refers to and setting the value given on the right
|
|
ASSUMPTIONS:
|
|
1. first object given on left side is "log4j" or "log4cpp"
|
|
2. all class names on right side are ignored because we
|
|
probably cannot resolve them anyway.
|
|
*/
|
|
|
|
// strip off the "log4j" or "log4cpp"
|
|
length = leftSide.find('.');
|
|
if (leftSide.substr(0, length) == "log4j" ||
|
|
leftSide.substr(0, length) == "log4cpp")
|
|
leftSide = leftSide.substr(length + 1);
|
|
|
|
// add to the map of properties
|
|
insert(value_type(leftSide, rightSide));
|
|
}
|
|
}
|
|
|
|
void Properties::save(std::ostream& out) {
|
|
for(const_iterator i = begin(); i != end(); ++i) {
|
|
out << (*i).first << "=" << (*i).second << std::endl;
|
|
}
|
|
}
|
|
|
|
int Properties::getInt(const std::string& property, int defaultValue) {
|
|
const_iterator key = find(property);
|
|
return (key == end()) ? defaultValue : std::atoi((*key).second.c_str());
|
|
}
|
|
|
|
bool Properties::getBool(const std::string& property, bool defaultValue) {
|
|
const_iterator key = find(property);
|
|
return (key == end()) ? defaultValue : ((*key).second == "true");
|
|
}
|
|
|
|
std::string Properties::getString(const std::string& property,
|
|
const char* defaultValue) {
|
|
const_iterator key = find(property);
|
|
return (key == end()) ? std::string(defaultValue) : (*key).second;
|
|
}
|
|
|
|
void Properties::_substituteVariables(std::string& value) {
|
|
std::string result;
|
|
|
|
std::string::size_type left = 0;
|
|
std::string::size_type right = value.find("${", left);
|
|
if (right == std::string::npos) {
|
|
// bail out early for 99% of cases
|
|
return;
|
|
}
|
|
|
|
while(true) {
|
|
result += value.substr(left, right - left);
|
|
if (right == std::string::npos) {
|
|
break;
|
|
}
|
|
|
|
left = right + 2;
|
|
right = value.find('}', left);
|
|
if (right == std::string::npos) {
|
|
// no close tag, use string literally
|
|
result += value.substr(left - 2);
|
|
break;
|
|
} else {
|
|
const std::string key = value.substr(left, right - left);
|
|
if (key == "${") {
|
|
result += "${";
|
|
} else {
|
|
char* env_value = std::getenv(key.c_str());
|
|
if (env_value) {
|
|
result += env_value;
|
|
} else {
|
|
const_iterator it = find(key);
|
|
if (it == end()) {
|
|
// not found assume empty;
|
|
} else {
|
|
result += (*it).second;
|
|
}
|
|
}
|
|
}
|
|
left = right + 1;
|
|
}
|
|
|
|
right = value.find("${", left);
|
|
}
|
|
|
|
value = result;
|
|
}
|
|
}
|