diff options
Diffstat (limited to 'src/shared/Config')
-rw-r--r-- | src/shared/Config/Config.cpp | 14 | ||||
-rw-r--r-- | src/shared/Config/Config.h | 9 | ||||
-rw-r--r-- | src/shared/Config/ConfigEnv.h | 4 | ||||
-rw-r--r-- | src/shared/Config/dotconfpp/dotconfpp.cpp | 76 | ||||
-rw-r--r-- | src/shared/Config/dotconfpp/dotconfpp.h | 18 | ||||
-rw-r--r-- | src/shared/Config/dotconfpp/mempool.cpp | 15 | ||||
-rw-r--r-- | src/shared/Config/dotconfpp/mempool.h | 10 |
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 |