www.pudn.com > zfxcengine-0.1.0.zip > ceLogConfig.cpp


/* $Id: ceLogConfig.cpp,v 1.5 2005/07/03 17:01:44 andreaskohn Exp $ */ 
#include  
#include  
 
#include  
#include  
#include  
 
namespace ZFXCE { 
namespace Logging {  
 
using std::make_pair; 
 
using std::fgets; 
using std::fopen; 
using std::fclose; 
using std::feof; 
using std::strcmp; 
using std::strlen; 
using std::strchr; 
using std::memmove; 
 
LOG_INIT("ZFXCE::Logging") 
//////////////////////////////////////////////////////////////////////////////// 
ceLogDomain* ceLogConfig::getDomain(string domain, string file) { 
	// TODO: domain inheritance? 
	ceLogDomain* logDomain = NULL; 
	map >::iterator it = getDomains().find(domain); 
	if (it == getDomains().end()) { 
		logDomain = new ceLogDomain(domain); 
		getDomains()[domain] = make_pair(logDomain, file); 
	} else { 
		logDomain = (*it).second.first; 
	} 
	 
	return logDomain; 
} 
//////////////////////////////////////////////////////////////////////////////// 
ceLogger* ceLogConfig::getLogger(string domain, string file) { 
	return new ceLogger(getDomain(domain, file)); 
} 
//////////////////////////////////////////////////////////////////////////////// 
ceLogLevel ceLogConfig::parseLogLevel(const string& level) { 
	if (level == "DEBUG") { 
		return LOG_DEBUG; 
	} else if (level == "INFO") { 
		return LOG_INFO; 
	} else if (level == "WARN") { 
		return LOG_WARN; 
	} else if (level == "ERROR") { 
		return LOG_ERROR; 
	} else if (level == "FATAL") { 
		return LOG_FATAL; 
	} 
	// not a valid level 
	return LOG_NUMLEVELS; 
} 
//////////////////////////////////////////////////////////////////////////////// 
const string ceLogConfig::getLogLevelName(const ceLogLevel level) { 
	switch (level) { 
		case LOG_DEBUG: return "DEBUG"; break; 
		case LOG_INFO: return "INFO"; break; 
		case LOG_WARN: return "WARN"; break; 
		case LOG_ERROR: return "ERROR"; break; 
		case LOG_FATAL: return "FATAL"; break; 
		case LOG_NUMLEVELS: 
		default: 
			return "(unknown log level)"; break; 
	} 
} 
//////////////////////////////////////////////////////////////////////////////// 
// [[domain][,level]=]filename 
//////////////////////////////////////////////////////////////////////////////// 
void ceLogConfig::parseLogDomain(const string& domain, string& targetDomain, ceLogLevel& targetLevel, ceLogStream*& targetStream) { 
	targetDomain = ""; 
	targetLevel = LOG_NUMLEVELS; 
	targetStream = NULL; 
 
	string::size_type pos = domain.rfind("="); 
	if (pos != string::npos) { 
		// XXX: perhaps we find a way to define other streams. 
		string streamFileName = domain.substr(pos + 1); 
		LOG_DEBUG1("stream %s, ", streamFileName.c_str()); 
		targetStream = new ceStdioStream(streamFileName);  
		string domainAndLevel = domain.substr(0, pos); 
		pos = domainAndLevel.find(","); 
		if (pos != string::npos) { 
			// we have both, but domain may be empty  
			targetDomain = domainAndLevel.substr(0, pos); 
			LOG_DEBUG1("domain %s, ", targetDomain.c_str()); 
			targetLevel = parseLogLevel(domainAndLevel.substr(pos + 1)); 
			LOG_DEBUG1("level %s\n", getLogLevelName(targetLevel).c_str()); 
		} else { 
			// we only have a domain 
			targetDomain = domainAndLevel; 
			LOG_DEBUG1("domain %s, all levels\n", targetDomain.c_str()); 
		} 
	} else { 
		targetStream = new ceStdioStream(domain); 
	} 
} 
//////////////////////////////////////////////////////////////////////////////// 
// XXX: should perhaps be moved to ceLogDomain sometimes. Be careful, circular friendships may happen. 
void ceLogConfig::dumpDomain(ceLogDomain* domain, string file) { 
	printf("%s (%s)\n", domain->getDomain().c_str(), file.c_str()); 
	for (ceLogLevel i = LOG_DEBUG; i < LOG_NUMLEVELS; i++) { 
		list streams = domain->getStreams(i, false); 
		bool enabled = domain->isLevelEnabled(i); 
		 
		if (enabled || streams.size() > 0) { 
			printf("\t%s (%s)\n", getLogLevelName(i).c_str(), (enabled?"enabled":"disabled")); 
			for (list::iterator it = streams.begin(); it != streams.end(); it++) { 
				printf("\t\t%s\n", (*it)->getInfo().c_str()); 
			} 
		} 
	} 
} 
//////////////////////////////////////////////////////////////////////////////// 
void ceLogConfig::dumpDomains() { 
	printf("Registered logging domains:\n"); 
	for (map >::const_iterator it = getDomains().begin(); it != getDomains().end(); it++) { 
		ceLogDomain* domain = (*it).second.first; 
		string file = (*it).second.second; 
		dumpDomain(domain, file); 
	} 
	printf("Default domain:\n"); 
	dumpDomain(&getDefaultDomain(), string("ceLogConfig.cpp")); 
} 
//////////////////////////////////////////////////////////////////////////////// 
void ceLogConfig::init(int& argc, char**& argv) { 
	list > domains; 
	string configFile = "zfxceLogging.config"; 
	bool doDumpDomains = false; 
	// parse commands  
	// and change argc and argv so that these args are removed 
	for (int i = 1; i < argc; i++) { 
		if (strcmp(argv[i], "--log") == 0) { 
			domains.push_back(make_pair(argv[++i], "[command line]")); 
		} else if (strcmp(argv[i], "--dump-domains") == 0) { 
			doDumpDomains = true; 
		} else if (strcmp(argv[i], "--log-config") == 0) { 
			configFile = string(argv[++i]); 
		} else if (strcmp(argv[i], "--log-help") == 0) { 
			printf("Arguments supported by the logging system are: \n"); 
			printf("	--log [[domain][,level]=]filename\n"); 
			printf("	--dump-domains\n"); 
			printf("	--log-config filename\n"); 
		} 
		// TODO: change argc, argv. 
	} 
 
	// open config file 
	FILE* f = fopen(configFile.c_str(), "r"); 
	if (f) { 
		const int MAX_LINE = 2048; 
		 
		char buffer[MAX_LINE]; 
		char nbuffer[MAX_LINE]; 
		while (!feof(f)) { 
			if (fgets(buffer, MAX_LINE, f) != NULL) { 
				buffer[strlen(buffer) - 1] = 0; 
				size_t j = 0; 
				for (size_t i = 0; i < strlen(buffer); i++) { 
					if (strchr(" \t\n\r", buffer[i]) == NULL) { 
						nbuffer[j++] = buffer[i]; 
					} 
				} 
				nbuffer[j] = 0; 
				if (strlen(nbuffer) > 0) { 
					domains.push_front(make_pair(nbuffer, configFile)); 
				} 
			} 
		} 
		fclose(f); 
	} 
	// initialize domains 
	string targetDomain = ""; 
	ceLogLevel targetLevel = LOG_NUMLEVELS; 
	ceLogStream* targetStream = NULL; 
	for (list >::const_iterator it = domains.begin(); it != domains.end(); it++) { 
		parseLogDomain((*it).first, targetDomain, targetLevel, targetStream); 
		if (targetStream == NULL) { 
			// ignore this line 
			continue; 
		} 
		if (targetDomain == "") { 
			if (targetLevel == LOG_NUMLEVELS) { 
				// insert for all 
				for (ceLogLevel i = LOG_DEBUG; i < LOG_NUMLEVELS; i++) { 
					getDefaultDomain().attachStream(i, targetStream); 
				} 
			} else { 
				getDefaultDomain().attachStream(targetLevel, targetStream); 
			} 
		} else { 
			ceLogDomain* domain = getDomain(targetDomain, (*it).second); 
			if (targetLevel == LOG_NUMLEVELS) { 
				// insert for all 
				for (ceLogLevel i = LOG_DEBUG; i < LOG_NUMLEVELS; i++) { 
					domain->attachStream(i, targetStream); 
					domain->enableLevel(i, true); 
				} 
			} else { 
				domain->attachStream(targetLevel, targetStream); 
				domain->enableLevel(targetLevel, true); 
			} 
		} 
	} 
 
	// if we were to dump domains, do it now. Auto-domains, command-line 
	// domains and domains created before init() are now initialized.  
	// We can't get information about stuff that gets initialized later. 
	if (doDumpDomains) { 
		dumpDomains(); 
	} 
	LOG_DEBUG("ceLogInit::init(): argc and argv are not updated.\n"); 
} 
//////////////////////////////////////////////////////////////////////////////// 
map >& ceLogConfig::getDomains() { 
	static map > _domains; 
	 
	return _domains; 
} 
//////////////////////////////////////////////////////////////////////////////// 
bool& ceLogConfig::getAllDisabled() { 
	static bool _allDisabled = false; 
	 
	return _allDisabled; 
} 
//////////////////////////////////////////////////////////////////////////////// 
ceLogDomain& ceLogConfig::getDefaultDomain() { 
	static ceLogDomain _defaultDomain("[default]"); 
	 
	return _defaultDomain; 
} 
//////////////////////////////////////////////////////////////////////////////// 
} // namespace Logging 
} // namespace ZFXCE