aboutsummaryrefslogtreecommitdiff
path: root/src/shared/Config
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/Config')
-rw-r--r--src/shared/Config/Config.cpp14
-rw-r--r--src/shared/Config/Config.h9
-rw-r--r--src/shared/Config/ConfigEnv.h4
-rw-r--r--src/shared/Config/dotconfpp/dotconfpp.cpp76
-rw-r--r--src/shared/Config/dotconfpp/dotconfpp.h18
-rw-r--r--src/shared/Config/dotconfpp/mempool.cpp15
-rw-r--r--src/shared/Config/dotconfpp/mempool.h10
7 files changed, 146 insertions, 0 deletions
diff --git a/src/shared/Config/Config.cpp b/src/shared/Config/Config.cpp
index 5636e17fd6d..b56b804b50a 100644
--- a/src/shared/Config/Config.cpp
+++ b/src/shared/Config/Config.cpp
@@ -17,38 +17,49 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#include "ConfigEnv.h"
#include "Policies/SingletonImp.h"
+
INSTANTIATE_SINGLETON_1(Config);
+
Config::Config() : mIgnoreCase(true), mConf(NULL)
{
}
+
Config::~Config()
{
delete mConf;
}
+
bool Config::SetSource(const char *file, bool ignorecase)
{
mIgnoreCase = ignorecase;
mFilename = file;
+
return Reload();
}
+
bool Config::Reload()
{
delete mConf;
+
mConf = new DOTCONFDocument(mIgnoreCase ?
DOTCONFDocument::CASEINSENSETIVE :
DOTCONFDocument::CASESENSETIVE);
+
if (mConf->setContent(mFilename.c_str()) == -1)
{
delete mConf;
mConf = NULL;
return false;
}
+
return true;
}
+
std::string Config::GetStringDefault(const char * name, std::string def)
{
if(!mConf)
@@ -58,6 +69,7 @@ std::string Config::GetStringDefault(const char * name, std::string def)
return std::string(def);
return std::string(node->getValue());
};
+
bool Config::GetBoolDefault(const char * name, const bool def)
{
if(!mConf)
@@ -73,6 +85,7 @@ bool Config::GetBoolDefault(const char * name, const bool def)
else
return false;
};
+
int32 Config::GetIntDefault(const char * name, const int32 def)
{
if(!mConf)
@@ -82,6 +95,7 @@ int32 Config::GetIntDefault(const char * name, const int32 def)
return def;
return atoi(node->getValue());
};
+
float Config::GetFloatDefault(const char * name, const float def)
{
if(!mConf)
diff --git a/src/shared/Config/Config.h b/src/shared/Config/Config.h
index 582c5266a8c..7070e6180c0 100644
--- a/src/shared/Config/Config.h
+++ b/src/shared/Config/Config.h
@@ -17,28 +17,37 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#ifndef CONFIG_H
#define CONFIG_H
+
#include <Policies/Singleton.h>
#include "Platform/Define.h"
+
class DOTCONFDocument;
+
class TRINITY_DLL_SPEC Config
{
public:
Config();
~Config();
+
bool SetSource(const char *file, bool ignorecase = true);
bool Reload();
+
std::string GetStringDefault(const char * name, std::string def);
bool GetBoolDefault(const char * name, const bool def);
int32 GetIntDefault(const char * name, const int32 def);
float GetFloatDefault(const char * name, const float def);
+
std::string GetFilename() const { return mFilename; }
private:
std::string mFilename;
bool mIgnoreCase;
DOTCONFDocument *mConf;
};
+
#define sConfig Trinity::Singleton<Config>::Instance()
+
#endif
diff --git a/src/shared/Config/ConfigEnv.h b/src/shared/Config/ConfigEnv.h
index c98fe6b38b0..75209a7fc6b 100644
--- a/src/shared/Config/ConfigEnv.h
+++ b/src/shared/Config/ConfigEnv.h
@@ -17,10 +17,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#if !defined(CONFIGENVIRONMENT_H)
+
#define CONFIGENVIRONMENT_H
+
#include "Common.h"
#include "dotconfpp/dotconfpp.h"
#include "Config.h"
+
#endif
diff --git a/src/shared/Config/dotconfpp/dotconfpp.cpp b/src/shared/Config/dotconfpp/dotconfpp.cpp
index 0492c69f805..e779637256e 100644
--- a/src/shared/Config/dotconfpp/dotconfpp.cpp
+++ b/src/shared/Config/dotconfpp/dotconfpp.cpp
@@ -1,6 +1,8 @@
#include "Common.h"
+
#include "dotconfpp.h"
+
#ifdef WIN32
#define PATH_MAX _MAX_PATH
#define strcasecmp stricmp
@@ -12,14 +14,17 @@
#include <stdint.h>
#include <strings.h>
#endif
+
#if !defined(R_OK)
#define R_OK 04
#endif
+
DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL),
values(NULL), valuesCount(0),
name(NULL), lineNum(0), fileName(NULL), closed(true)
{
}
+
DOTCONFDocumentNode::~DOTCONFDocumentNode()
{
free(name);
@@ -30,12 +35,14 @@ DOTCONFDocumentNode::~DOTCONFDocumentNode()
free(values);
}
}
+
void DOTCONFDocumentNode::pushValue(char * _value)
{
++valuesCount;
values = (char**)realloc(values, valuesCount*sizeof(char*));
values[valuesCount-1] = strdup(_value);
}
+
const char* DOTCONFDocumentNode::getValue(int index) const
{
if(index >= valuesCount){
@@ -43,6 +50,7 @@ const char* DOTCONFDocumentNode::getValue(int index) const
}
return values[index];
}
+
DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity):
mempool(NULL),
curParent(NULL), curPrev(NULL), curLine(0), file(NULL), fileName(NULL)
@@ -52,9 +60,11 @@ DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity)
} else {
cmp_func = strcasecmp;
}
+
mempool = new AsyncDNSMemPool(1024);
mempool->initialize();
}
+
DOTCONFDocument::~DOTCONFDocument()
{
for(std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i){
@@ -69,6 +79,7 @@ DOTCONFDocument::~DOTCONFDocument()
free(fileName);
delete mempool;
}
+
int DOTCONFDocument::cleanupLine(char * line)
{
char * start = line;
@@ -76,12 +87,15 @@ int DOTCONFDocument::cleanupLine(char * line)
bool multiline = false;
bool concat = false;
char * word = NULL;
+
if(!words.empty() && quoted)
concat = true;
+
while(*line){
if((*line == '#' || *line == ';') && !quoted){
*bg = 0;
if(strlen(start)){
+
if(concat){
word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
strcpy(word, words.back());
@@ -98,6 +112,7 @@ int DOTCONFDocument::cleanupLine(char * line)
if(*line == '=' && !quoted){
*line = ' ';continue;
}
+
// Allowing \" in there causes problems with directory paths
// like "C:\TrinIty\"
//if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){
@@ -116,6 +131,7 @@ int DOTCONFDocument::cleanupLine(char * line)
if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){
*bg = 0;
if(strlen(start)){
+
if(concat){
word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
strcpy(word, words.back());
@@ -137,6 +153,7 @@ int DOTCONFDocument::cleanupLine(char * line)
if(isspace((unsigned char)*line) && !quoted){
*bg++ = 0;
if(strlen(start)){
+
if(concat){
word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
strcpy(word, words.back());
@@ -150,16 +167,20 @@ int DOTCONFDocument::cleanupLine(char * line)
}
start = bg;
while(isspace((unsigned char)*++line)) {}
+
continue;
}
*bg++ = *line++;
}
+
if(quoted && !multiline){
error(curLine, fileName, "unterminated quote");
return -1;
}
+
return multiline?1:0;
}
+
int DOTCONFDocument::parseLine()
{
char * word = NULL;
@@ -167,21 +188,26 @@ int DOTCONFDocument::parseLine()
char * nodeValue = NULL;
DOTCONFDocumentNode * tagNode = NULL;
bool newNode = false;
+
for(std::list<char*>::iterator i = words.begin(); i != words.end(); ++i) {
word = *i;
+
if(*word == '<'){
newNode = true;
}
+
if(newNode){
nodeValue = NULL;
nodeName = NULL;
newNode = false;
}
+
size_t wordLen = strlen(word);
if(word[wordLen-1] == '>'){
word[wordLen-1] = 0;
newNode = true;
}
+
if(nodeName == NULL){
nodeName = word;
bool closed = true;
@@ -216,9 +242,11 @@ int DOTCONFDocument::parseLine()
if(!nodeTree.empty()){
DOTCONFDocumentNode * prev = nodeTree.back();
if(prev->closed){
+
curPrev->nextNode = tagNode;
tagNode->previousNode = curPrev;
tagNode->parentNode = curParent;
+
} else {
prev->childNode = tagNode;
tagNode->parentNode = prev;
@@ -232,6 +260,7 @@ int DOTCONFDocument::parseLine()
tagNode->pushValue(nodeValue);
}
}
+
return 0;
}
int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent)
@@ -240,8 +269,10 @@ int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent)
int ret = 0;
curLine = 0;
curParent = _parent;
+
quoted = false;
size_t slen = 0;
+
while(fgets(str, 511, file)){
++curLine;
slen = strlen(str);
@@ -266,11 +297,14 @@ int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent)
}
}
}
+
return ret;
}
+
int DOTCONFDocument::checkConfig(const std::list<DOTCONFDocumentNode*>::iterator & from)
{
int ret = 0;
+
DOTCONFDocumentNode * tagNode = NULL;
int vi = 0;
for(std::list<DOTCONFDocumentNode*>::iterator i = from; i != nodeTree.end(); ++i){
@@ -282,6 +316,7 @@ int DOTCONFDocument::checkConfig(const std::list<DOTCONFDocumentNode*>::iterator
}
vi = 0;
while( vi < tagNode->valuesCount ){
+
if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){
ret = macroSubstitute(tagNode, vi );
mempool->free();
@@ -295,18 +330,24 @@ int DOTCONFDocument::checkConfig(const std::list<DOTCONFDocumentNode*>::iterator
break;
}
}
+
return ret;
}
+
int DOTCONFDocument::setContent(const char * _fileName)
{
int ret = 0;
char realpathBuf[PATH_MAX];
+
if(realpath(_fileName, realpathBuf) == NULL){
error(0, NULL, "realpath(%s) failed: %s", _fileName, strerror(errno));
return -1;
}
+
fileName = strdup(realpathBuf);
+
processedFiles.push_back(strdup(realpathBuf));
+
if(( file = fopen(fileName, "r")) == NULL){
error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno));
return -1;
@@ -316,12 +357,17 @@ int DOTCONFDocument::setContent(const char * _fileName)
fgets((char*)&utf8header, 4, file); // Try read header
if (utf8header!=0x00BFBBEF) // If not exist
fseek(file, 0, SEEK_SET); // Reset read position
+
ret = parseFile();
+
(void) fclose(file);
+
if(!ret){
+
if( (ret = checkConfig(nodeTree.begin())) == -1){
return -1;
}
+
std::list<DOTCONFDocumentNode*>::iterator from;
DOTCONFDocumentNode * tagNode = NULL;
int vi = 0;
@@ -338,6 +384,7 @@ int DOTCONFDocument::setContent(const char * _fileName)
error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", tagNode->values[vi], strerror(errno));
return -1;
}
+
bool processed = false;
for(std::list<char*>::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); ++itInode){
if(!strcmp(*itInode, realpathBuf)){
@@ -348,14 +395,18 @@ int DOTCONFDocument::setContent(const char * _fileName)
if(processed){
break;
}
+
processedFiles.push_back(strdup(realpathBuf));
+
file = fopen(tagNode->values[vi], "r");
if(file == NULL){
error(tagNode->lineNum, fileName, "failed to open file '%s': %s", tagNode->values[vi], strerror(errno));
return -1;
}
+
fileName = strdup(realpathBuf);
from = nodeTree.end(); --from;
+
ret = parseFile();
(void) fclose(file);
if(ret == -1)
@@ -368,11 +419,14 @@ int DOTCONFDocument::setContent(const char * _fileName)
}
}
+
if(!requiredOptions.empty())
ret = checkRequiredOptions();
}
+
return ret;
}
+
int DOTCONFDocument::checkRequiredOptions()
{
for(std::list<char*>::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci){
@@ -390,30 +444,40 @@ int DOTCONFDocument::checkRequiredOptions()
}
return 0;
}
+
void DOTCONFDocument::error(int lineNum, const char * fileName_, const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
+
size_t len = (lineNum!=0?strlen(fileName_):0) + strlen(fmt) + 50;
char * buf = (char*)mempool->alloc(len);
+
if(lineNum)
(void) snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName_, lineNum, fmt);
else
(void) snprintf(buf, len, "DOTCONF++: %s\n", fmt);
+
(void) vfprintf(stderr, buf, args);
+
va_end(args);
}
+
char * DOTCONFDocument::getSubstitution(char * macro, int lineNum)
{
char * buf = NULL;
char * variable = macro+2;
+
char * endBr = strchr(macro, '}');
+
if(!endBr){
error(lineNum, fileName, "unterminated '{'");
return NULL;
}
*endBr = 0;
+
char * defaultValue = strchr(variable, ':');
+
if(defaultValue){
*defaultValue++ = 0;
if(*defaultValue != '-'){
@@ -428,6 +492,7 @@ char * DOTCONFDocument::getSubstitution(char * macro, int lineNum)
} else {
defaultValue = NULL;
}
+
char * subs = getenv(variable);
if( subs ){
buf = mempool->strdup(subs);
@@ -454,6 +519,7 @@ char * DOTCONFDocument::getSubstitution(char * macro, int lineNum)
}
return buf;
}
+
int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex)
{
int ret = 0;
@@ -462,6 +528,7 @@ int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueInd
char * value = (char*)mempool->alloc(valueLen);
char * v = value;
char * subs = NULL;
+
while(*macro){
if(*macro == '$' && *(macro+1) == '{'){
char * m = strchr(macro, '}');
@@ -481,10 +548,12 @@ int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueInd
*v++ = *macro++;
}
*v = 0;
+
free(tagNode->values[valueIndex]);
tagNode->values[valueIndex] = strdup(value);
return ret;
}
+
const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const
{
if ( !nodeTree.empty() ) {
@@ -493,19 +562,25 @@ const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const
return NULL;
}
}
+
const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const
{
+
std::list<DOTCONFDocumentNode*>::const_iterator i = nodeTree.begin();
+
if(startNode == NULL)
startNode = parentNode;
+
if(startNode != NULL){
while( i != nodeTree.end() && (*i) != startNode ){
++i;
}
if( i != nodeTree.end() ) ++i;
}
+
for(; i!=nodeTree.end(); ++i){
+
if((*i)->parentNode != parentNode){
continue;
}
@@ -515,6 +590,7 @@ const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, con
}
return NULL;
}
+
void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames)
{
while(*requiredOptionNames){
diff --git a/src/shared/Config/dotconfpp/dotconfpp.h b/src/shared/Config/dotconfpp/dotconfpp.h
index 687753eb807..51455854ee7 100644
--- a/src/shared/Config/dotconfpp/dotconfpp.h
+++ b/src/shared/Config/dotconfpp/dotconfpp.h
@@ -1,17 +1,24 @@
+
#ifndef DOTCONFPP_H
#define DOTCONFPP_H
+
#include <list>
+
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
+
#include <sys/types.h>
#include <sys/stat.h>
+
#include "mempool.h"
+
class DOTCONFDocument;
+
class DOTCONFDocumentNode
{
friend class DOTCONFDocument;
@@ -27,12 +34,16 @@ private:
int lineNum;
char * fileName;
bool closed;
+
void pushValue(char * _value);
+
public:
DOTCONFDocumentNode();
~DOTCONFDocumentNode();
+
const char * getConfigurationFileName()const { return fileName; }
int getConfigurationLineNumber() const { return lineNum; }
+
const DOTCONFDocumentNode * getNextNode() const { return nextNode; }
const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; }
const DOTCONFDocumentNode * getParentNode() const { return parentNode; }
@@ -41,6 +52,7 @@ public:
const char * getName() const { return name; }
const DOTCONFDocument * getDocument() const { return document; }
};
+
class DOTCONFDocument
{
public:
@@ -59,6 +71,7 @@ private:
char * fileName;
std::list<char*> words;
int (*cmp_func)(const char *, const char *);
+
int checkRequiredOptions();
int parseLine();
int parseFile(DOTCONFDocumentNode * _parent = NULL);
@@ -66,15 +79,20 @@ private:
int cleanupLine(char * line);
char * getSubstitution(char * macro, int lineNum);
int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex);
+
protected:
virtual void error(int lineNum, const char * fileName, const char * fmt, ...) ATTR_PRINTF(4,5);
+
public:
DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSETIVE);
virtual ~DOTCONFDocument();
+
int setContent(const char * _fileName);
+
void setRequiredOptionNames(const char ** requiredOptionNames);
const DOTCONFDocumentNode * getFirstNode() const;
const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const;
};
+
#endif
diff --git a/src/shared/Config/dotconfpp/mempool.cpp b/src/shared/Config/dotconfpp/mempool.cpp
index 019cfe3cb86..cec8e8d119f 100644
--- a/src/shared/Config/dotconfpp/mempool.cpp
+++ b/src/shared/Config/dotconfpp/mempool.cpp
@@ -1,20 +1,25 @@
+
#include "mempool.h"
+
AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size):
pool(NULL), pos(0), size(_size)
{
pool = ::malloc(size);
}
+
AsyncDNSMemPool::PoolChunk::~PoolChunk()
{
::free(pool);
}
+
AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize):
chunks(NULL), chunksCount(0), defaultSize(_defaultSize),
poolUsage(0), poolUsageCounter(0)
{
}
+
AsyncDNSMemPool::~AsyncDNSMemPool()
{
for(size_t i = 0; i<chunksCount; ++i){
@@ -22,15 +27,19 @@ AsyncDNSMemPool::~AsyncDNSMemPool()
}
::free(chunks);
}
+
int AsyncDNSMemPool::initialize()
{
chunksCount = 1;
chunks = (PoolChunk**)::malloc(sizeof(PoolChunk*));
if(chunks == NULL)
return -1;
+
chunks[chunksCount-1] = new PoolChunk(defaultSize);
+
return 0;
}
+
void AsyncDNSMemPool::addNewChunk(size_t size)
{
++chunksCount;
@@ -40,6 +49,7 @@ void AsyncDNSMemPool::addNewChunk(size_t size)
else
chunks[chunksCount-1] = new PoolChunk(size);
}
+
void * AsyncDNSMemPool::alloc(size_t size)
{
PoolChunk * chunk = NULL;
@@ -54,17 +64,20 @@ void * AsyncDNSMemPool::alloc(size_t size)
chunks[chunksCount-1]->pos = size;
return chunks[chunksCount-1]->pool;
}
+
void AsyncDNSMemPool::free()
{
size_t pu = 0;
size_t psz = 0;
++poolUsageCounter;
+
for(size_t i = 0; i<chunksCount; ++i){
pu += chunks[i]->pos;
psz += chunks[i]->size;
chunks[i]->pos = 0;
}
poolUsage=(poolUsage>pu)?poolUsage:pu;
+
if(poolUsageCounter >= 10 && chunksCount > 1){
psz -= chunks[chunksCount-1]->size;
if(poolUsage < psz){
@@ -75,10 +88,12 @@ void AsyncDNSMemPool::free()
poolUsageCounter = 0;
}
}
+
void * AsyncDNSMemPool::calloc(size_t size)
{
return ::memset(this->alloc(size), 0, size);
}
+
char * AsyncDNSMemPool::strdup(const char *str)
{
return ::strcpy((char*)this->alloc(strlen(str)+1), str);
diff --git a/src/shared/Config/dotconfpp/mempool.h b/src/shared/Config/dotconfpp/mempool.h
index 6bf71eb6b54..81c01d15a58 100644
--- a/src/shared/Config/dotconfpp/mempool.h
+++ b/src/shared/Config/dotconfpp/mempool.h
@@ -1,13 +1,17 @@
+
#ifndef ASYNC_DNS_MEMPOOL_H
#define ASYNC_DNS_MEMPOOL_H
+
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
+
#undef free
#undef calloc
#undef strdup
+
class AsyncDNSMemPool
{
private:
@@ -15,23 +19,29 @@ private:
void * pool;
size_t pos;
size_t size;
+
PoolChunk(size_t _size);
~PoolChunk();
};
PoolChunk ** chunks;
size_t chunksCount;
size_t defaultSize;
+
size_t poolUsage;
size_t poolUsageCounter;
+
void addNewChunk(size_t size);
+
public:
AsyncDNSMemPool(size_t _defaultSize = 4096);
virtual ~AsyncDNSMemPool();
+
int initialize();
void free();
void * alloc(size_t size);
void * calloc(size_t size);
char * strdup(const char *str);
};
+
#endif