Contents of misc.cpp relocated
The functions formerly defined in misc.cpp are now defined in the source files corresponding to the header files where they were declared.
This commit is contained in:
parent
8150f49c2c
commit
e3b5ee802e
7 changed files with 1952 additions and 2164 deletions
|
|
@ -12,9 +12,6 @@
|
|||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
// See file misc.cpp for implementations of methods/functions declared
|
||||
// here.
|
||||
|
||||
namespace Cantera
|
||||
{
|
||||
|
||||
|
|
@ -75,8 +72,7 @@ class CanteraError : public std::exception
|
|||
public:
|
||||
//! Normal Constructor for the CanteraError base class
|
||||
/*!
|
||||
* This class doesn't have any storage associated with it. In its
|
||||
* constructor, a call to the Application class is made to store
|
||||
* In the constructor, a call to the Application class is made to store
|
||||
* the strings associated with the generated error condition.
|
||||
*
|
||||
* @param procedure String name for the function within which the error was
|
||||
|
|
@ -86,14 +82,15 @@ public:
|
|||
CanteraError(std::string procedure, std::string msg);
|
||||
|
||||
//! Destructor for base class does nothing
|
||||
virtual ~CanteraError() throw();
|
||||
virtual ~CanteraError() throw() {};
|
||||
|
||||
protected:
|
||||
//! Empty base constructor is made protected so that it may be used only by
|
||||
//! inherited classes.
|
||||
/*!
|
||||
* We want to discourage throwing an error containing no information.
|
||||
*/
|
||||
CanteraError();
|
||||
CanteraError() {};
|
||||
};
|
||||
|
||||
//! Array size error.
|
||||
|
|
|
|||
|
|
@ -405,9 +405,6 @@ void close_XML_File(std::string file);
|
|||
* A, B, and C to be written (in nested HTML lists), loglevel =
|
||||
* 2 results in messages only being written from A and B, etc.
|
||||
*/
|
||||
//@{
|
||||
//@}
|
||||
|
||||
|
||||
//!Create a new group for log messages.
|
||||
/*!
|
||||
|
|
@ -508,7 +505,6 @@ inline void endLogGroup(std::string title="") {}
|
|||
inline void write_logfile(std::string file = "log.html") {}
|
||||
#endif
|
||||
|
||||
|
||||
//! This routine will locate an XML node in either the input
|
||||
//! XML tree or in another input file specified by the file
|
||||
//! part of the file_ID string.
|
||||
|
|
|
|||
810
src/base/application.cpp
Normal file
810
src/base/application.cpp
Normal file
|
|
@ -0,0 +1,810 @@
|
|||
#include "application.h"
|
||||
|
||||
#include "cantera/base/ctexceptions.h"
|
||||
#include "cantera/base/ctml.h"
|
||||
#include "cantera/base/stringUtils.h"
|
||||
#include "cantera/base/xml.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
using std::string;
|
||||
using std::endl;
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "advapi32")
|
||||
#endif
|
||||
|
||||
// If running multiple threads in a cpp application, the Application class
|
||||
// is the only internal object that is single instance with static data.
|
||||
// Synchronize access to those data structures Using macros to avoid
|
||||
// polluting code with a lot of ifdef's
|
||||
|
||||
#ifdef THREAD_SAFE_CANTERA
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
//! Mutex for input directory access
|
||||
static boost::mutex dir_mutex;
|
||||
|
||||
//! Mutex for access to string messages
|
||||
static boost::mutex msg_mutex;
|
||||
|
||||
//! Mutex for creating singeltons within the application object
|
||||
static boost::mutex app_mutex;
|
||||
|
||||
// Mutex for controlling access to the log file
|
||||
//static boost::mutex log_mutex;
|
||||
|
||||
//! Mutex for controlling access to XML file storage
|
||||
static boost::mutex xml_mutex;
|
||||
|
||||
//! Macro for locking input directory access
|
||||
#define DIR_LOCK() boost::mutex::scoped_lock d_lock(dir_mutex)
|
||||
|
||||
//! Macro for locking access to string messages
|
||||
#define MSG_LOCK() boost::mutex::scoped_lock m_lock(msg_mutex)
|
||||
|
||||
//! Macro for locking creating singletons in the application state
|
||||
#define APP_LOCK() boost::mutex::scoped_lock a_lock(app_mutex)
|
||||
|
||||
//! Macro for locking XML file writing
|
||||
#define XML_LOCK() boost::mutex::scoped_lock x_lock(xml_mutex)
|
||||
|
||||
#ifdef WITH_HTML_LOGS
|
||||
//static boost::mutex html_mutex; // html logs
|
||||
//#define HTML_LOCK() boost::mutex::scoped_lock h_lock(html_mutex)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
#include <windows.h>
|
||||
typedef unsigned int cthreadId_t ;
|
||||
class thread_equal
|
||||
{
|
||||
public:
|
||||
bool operator()(cthreadId_t L, cthreadId_t R) {
|
||||
return L == R ;
|
||||
}
|
||||
} ;
|
||||
cthreadId_t getThisThreadId()
|
||||
{
|
||||
return ::GetCurrentThreadId() ;
|
||||
}
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
|
||||
typedef pthread_t cthreadId_t ;
|
||||
class thread_equal
|
||||
{
|
||||
public:
|
||||
bool operator()(cthreadId_t L, cthreadId_t R) {
|
||||
return pthread_equal(L, R) ;
|
||||
}
|
||||
} ;
|
||||
cthreadId_t getThisThreadId()
|
||||
{
|
||||
return pthread_self() ;
|
||||
}
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
typedef MPTaskID cthreadId_t ;
|
||||
class thread_equal
|
||||
{
|
||||
public:
|
||||
bool operator()(cthreadId_t L, cthreadId_t R) {
|
||||
return L == R ;
|
||||
}
|
||||
} ;
|
||||
cthreadId_t getThisThreadId()
|
||||
{
|
||||
return MPCurrentTaskID() ;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define DIR_LOCK()
|
||||
#define MSG_LOCK()
|
||||
#define APP_LOCK()
|
||||
//#define LOG_LOCK()
|
||||
#define XML_LOCK()
|
||||
|
||||
#ifdef WITH_HTML_LOGS
|
||||
//#define HTML_LOCK()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
Application::Messages::Messages() :
|
||||
errorMessage(0),
|
||||
errorRoutine(0),
|
||||
logwriter(0)
|
||||
#ifdef WITH_HTML_LOGS
|
||||
,xmllog(0),
|
||||
current(0),
|
||||
loglevel(0),
|
||||
loglevels(0),
|
||||
loggroups(0)
|
||||
#endif
|
||||
{
|
||||
// install a default logwriter that writes to standard
|
||||
// output / standard error
|
||||
logwriter = new Logger();
|
||||
}
|
||||
|
||||
Application::Messages::Messages(const Messages& r) :
|
||||
errorMessage(r.errorMessage),
|
||||
errorRoutine(r.errorRoutine),
|
||||
logwriter(0)
|
||||
#ifdef WITH_HTML_LOGS
|
||||
, xmllog(r.xmllog),
|
||||
current(r.current),
|
||||
loglevel(r.loglevel),
|
||||
loglevels(r.loglevels),
|
||||
loggroups(r.loggroups)
|
||||
#endif
|
||||
{
|
||||
// install a default logwriter that writes to standard
|
||||
// output / standard error
|
||||
logwriter = new Logger(*(r.logwriter));
|
||||
}
|
||||
|
||||
Application::Messages& Application::Messages::operator=(const Messages& r) {
|
||||
if (this == &r) {
|
||||
return *this;
|
||||
}
|
||||
errorMessage = r.errorMessage;
|
||||
errorRoutine = r.errorRoutine;
|
||||
logwriter = new Logger(*(r.logwriter));
|
||||
#ifdef WITH_HTML_LOGS
|
||||
xmllog = r.xmllog;
|
||||
current = r.current;
|
||||
loglevel = r.loglevel;
|
||||
loglevels = r.loglevels;
|
||||
loggroups = r.loggroups;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
Application::Messages::~Messages() {
|
||||
delete logwriter;
|
||||
#ifdef WITH_HTML_LOGS
|
||||
if (xmllog) {
|
||||
write_logfile("orphan");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set an error condition in the application class without throwing an exception
|
||||
void Application::Messages::addError(std::string r, std::string msg)
|
||||
{
|
||||
errorMessage.push_back(msg);
|
||||
errorRoutine.push_back(r);
|
||||
}
|
||||
|
||||
// Return the number of errors encountered so far
|
||||
int Application::Messages::getErrorCount()
|
||||
{
|
||||
return static_cast<int>(errorMessage.size()) ;
|
||||
}
|
||||
|
||||
void Application::Messages::setLogger(Logger* _logwriter)
|
||||
{
|
||||
if (logwriter == _logwriter) {
|
||||
return ;
|
||||
}
|
||||
if (logwriter != 0) {
|
||||
delete logwriter;
|
||||
logwriter = 0 ;
|
||||
}
|
||||
logwriter = _logwriter;
|
||||
}
|
||||
|
||||
// Return an integer specifying the application environment.
|
||||
int Application::Messages::getUserEnv()
|
||||
{
|
||||
return logwriter->env() ;
|
||||
}
|
||||
|
||||
// Write an error message and terminate execution
|
||||
void Application::Messages::logerror(const std::string& msg)
|
||||
{
|
||||
logwriter->error(msg) ;
|
||||
}
|
||||
|
||||
#ifdef WITH_HTML_LOGS
|
||||
|
||||
// Write a message to the screen
|
||||
void Application::Messages::writelog(const char* pszmsg)
|
||||
{
|
||||
logwriter->write(pszmsg) ;
|
||||
}
|
||||
|
||||
// Write a message to the screen
|
||||
void Application::Messages::writelog(const std::string& msg)
|
||||
{
|
||||
logwriter->write(msg);
|
||||
}
|
||||
|
||||
// Write an endl to the screen and flush output
|
||||
void Application::Messages::writelogendl()
|
||||
{
|
||||
logwriter->writeendl();
|
||||
}
|
||||
|
||||
void Application::Messages::beginLogGroup(std::string title, int _loglevel /*=-99*/)
|
||||
{
|
||||
// loglevel is a member of the Messages class.
|
||||
if (_loglevel != -99) {
|
||||
loglevel = _loglevel;
|
||||
} else {
|
||||
loglevel--;
|
||||
}
|
||||
if (loglevel <= 0) {
|
||||
return;
|
||||
}
|
||||
// Add the current loglevel to the vector of loglevels
|
||||
loglevels.push_back(loglevel);
|
||||
// Add the title of the current logLevel to the vector of titles
|
||||
loggroups.push_back(title);
|
||||
// If we haven't started an XML tree for the log file, do so here
|
||||
if (xmllog == 0) {
|
||||
// The top of this tree will have a zero pointer.
|
||||
xmllog = new XML_Node("html");
|
||||
current = &xmllog->addChild("ul");
|
||||
}
|
||||
// Add two children to the XML tree.
|
||||
current = ¤t->addChild("li","<b>"+title+"</b>");
|
||||
current = ¤t->addChild("ul");
|
||||
}
|
||||
|
||||
void Application::Messages::addLogEntry(std::string tag, std::string value)
|
||||
{
|
||||
if (loglevel > 0 && current) {
|
||||
current->addChild("li",tag+": "+value);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Messages::addLogEntry(std::string tag, doublereal value)
|
||||
{
|
||||
if (loglevel > 0 && current) {
|
||||
current->addChild("li",tag+": "+fp2str(value));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Messages::addLogEntry(std::string tag, int value)
|
||||
{
|
||||
if (loglevel > 0 && current) {
|
||||
current->addChild("li",tag+": "+int2str(value));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Messages::addLogEntry(std::string msg)
|
||||
{
|
||||
if (loglevel > 0 && current) {
|
||||
current->addChild("li",msg);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Messages::endLogGroup(std::string title)
|
||||
{
|
||||
if (loglevel <= 0) {
|
||||
return;
|
||||
}
|
||||
AssertThrowMsg(current, "Application::Messages::endLogGroup",
|
||||
"Error while ending a LogGroup. This is probably due to an unmatched"
|
||||
" beginnning and ending group");
|
||||
current = current->parent();
|
||||
AssertThrowMsg(current, "Application::Messages::endLogGroup",
|
||||
"Error while ending a LogGroup. This is probably due to an unmatched"
|
||||
" beginnning and ending group");
|
||||
current = current->parent();
|
||||
// Get the loglevel of the previous level and get rid of
|
||||
// vector entry in loglevels.
|
||||
loglevel = loglevels.back();
|
||||
loglevels.pop_back();
|
||||
if (title != "" && title != loggroups.back()) {
|
||||
writelog("Logfile error."
|
||||
"\n beginLogGroup: "+ loggroups.back()+
|
||||
"\n endLogGroup: "+title+"\n");
|
||||
write_logfile("logerror");
|
||||
} else if (loggroups.size() == 1) {
|
||||
write_logfile(loggroups.back()+"_log");
|
||||
loggroups.clear();
|
||||
loglevels.clear();
|
||||
} else {
|
||||
loggroups.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Messages::write_logfile(std::string file)
|
||||
{
|
||||
if (!xmllog) {
|
||||
return;
|
||||
}
|
||||
std::string::size_type idot = file.rfind('.');
|
||||
std::string ext = "";
|
||||
std::string nm = file;
|
||||
if (idot != std::string::npos) {
|
||||
ext = file.substr(idot, file.size());
|
||||
nm = file.substr(0,idot);
|
||||
} else {
|
||||
ext = ".html";
|
||||
nm = file;
|
||||
}
|
||||
|
||||
// see if file exists. If it does, find an integer that
|
||||
// can be appended to the name to create the name of a file
|
||||
// that does not exist.
|
||||
std::string fname = nm + ext;
|
||||
std::ifstream f(fname.c_str());
|
||||
if (f) {
|
||||
int n = 0;
|
||||
while (1 > 0) {
|
||||
n++;
|
||||
fname = nm + int2str(n) + ext;
|
||||
std::ifstream f(fname.c_str());
|
||||
if (!f) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now we have a file name that does not correspond to any
|
||||
// existing file. Open it as an output stream, and dump the
|
||||
// XML (HTML) tree to it.
|
||||
|
||||
if (xmllog) {
|
||||
std::ofstream f(fname.c_str());
|
||||
// go to the top of the tree, and write it all.
|
||||
xmllog->root().write(f);
|
||||
f.close();
|
||||
writelog("Log file " + fname + " written.\n");
|
||||
delete xmllog;
|
||||
xmllog = 0;
|
||||
current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // WITH_HTML_LOGS
|
||||
|
||||
Application::Application() :
|
||||
inputDirs(0),
|
||||
stop_on_error(false),
|
||||
options(),
|
||||
tmp_dir("."),
|
||||
xmlfiles(),
|
||||
m_sleep("1"),
|
||||
pMessenger() {
|
||||
#if !defined( THREAD_SAFE_CANTERA )
|
||||
pMessenger = std::auto_ptr<Messages>(new Messages());
|
||||
#endif
|
||||
// if TMP or TEMP is set, use it for the temporary
|
||||
// directory
|
||||
char* ctmpdir = getenv("CANTERA_TMPDIR");
|
||||
if (ctmpdir != 0) {
|
||||
tmp_dir = std::string(ctmpdir);
|
||||
} else {
|
||||
char* tmpdir = getenv("TMP");
|
||||
if (tmpdir == 0) {
|
||||
tmpdir = getenv("TEMP");
|
||||
}
|
||||
if (tmpdir != 0) {
|
||||
tmp_dir = std::string(tmpdir);
|
||||
}
|
||||
}
|
||||
|
||||
// if SLEEP is set, use it as the sleep time
|
||||
char* sleepstr = getenv("SLEEP");
|
||||
if (sleepstr != 0) {
|
||||
m_sleep = std::string(sleepstr);
|
||||
}
|
||||
|
||||
// install a default logwriter that writes to standard
|
||||
// output / standard error
|
||||
// logwriter = new Logger();
|
||||
//#ifdef WITH_HTML_LOGS
|
||||
// // HTML log files
|
||||
// xmllog = 0;
|
||||
// current = 0;
|
||||
// loglevel = 0;
|
||||
//#endif
|
||||
setDefaultDirectories();
|
||||
#if defined(THREAD_SAFE_CANTERA)
|
||||
Unit::units() ;
|
||||
#endif
|
||||
}
|
||||
|
||||
Application* Application::Instance() {
|
||||
APP_LOCK();
|
||||
if (Application::s_app == 0) {
|
||||
Application::s_app = new Application();
|
||||
}
|
||||
return s_app;
|
||||
}
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
std::map<std::string, XML_Node*>::iterator pos;
|
||||
for (pos = xmlfiles.begin(); pos != xmlfiles.end(); ++pos) {
|
||||
pos->second->unlock();
|
||||
delete pos->second;
|
||||
pos->second = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::ApplicationDestroy() {
|
||||
APP_LOCK();
|
||||
if (Application::s_app != 0) {
|
||||
delete Application::s_app;
|
||||
Application::s_app = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::thread_complete()
|
||||
{
|
||||
#if defined(THREAD_SAFE_CANTERA)
|
||||
pMessenger.removeThreadMessages() ;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
XML_Node* Application::get_XML_File(std::string file, int debug)
|
||||
{
|
||||
XML_LOCK();
|
||||
std::string path = "";
|
||||
/*
|
||||
try {
|
||||
path = findInputFile(file);
|
||||
}
|
||||
catch (CanteraError) {
|
||||
string::size_type idot = file.rfind('.');
|
||||
string ext = "";
|
||||
if (idot != string::npos) {
|
||||
ext = file.substr(idot, file.size());
|
||||
string ctifile = file.substr(0,idot)+".cti";
|
||||
try {
|
||||
path = findInputFile(ctifile);
|
||||
}
|
||||
catch (CanteraError) {
|
||||
path = findInputFile(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
path = findInputFile(file);
|
||||
}
|
||||
*/
|
||||
// The code above will try to process a cti file if the xml
|
||||
// file is not found. But I (dgg) don't think it makes much sense,
|
||||
// so it is replaced by:
|
||||
path = findInputFile(file);
|
||||
#ifdef _WIN32
|
||||
// RFB: For Windows make the path POSIX compliant so code looking for directory
|
||||
// separators is simpler. Just look for '/' not both '/' and '\\'
|
||||
std::replace_if(path.begin(), path.end(),
|
||||
std::bind2nd(std::equal_to<char>(), '\\'), '/') ;
|
||||
#endif
|
||||
|
||||
string ff = path;
|
||||
if (xmlfiles.find(path)
|
||||
== xmlfiles.end()) {
|
||||
/*
|
||||
* Check whether or not the file is XML. If not, it will
|
||||
* be first processed with the preprocessor. We determine
|
||||
* whether it is an XML file by looking at the file extension.
|
||||
*/
|
||||
string::size_type idot = path.rfind('.');
|
||||
string ext;
|
||||
if (idot != string::npos) {
|
||||
ext = path.substr(idot, path.size());
|
||||
} else {
|
||||
ext = "";
|
||||
idot = path.size();
|
||||
}
|
||||
if (ext != ".xml" && ext != ".ctml") {
|
||||
/*
|
||||
* We will assume that we are trying to open a cti file.
|
||||
* First, determine the name of the xml file, ff, derived from
|
||||
* the cti file.
|
||||
* In all cases, we will write the xml file to the current
|
||||
* directory.
|
||||
*/
|
||||
string::size_type islash = path.rfind('/');
|
||||
if (islash != string::npos) {
|
||||
ff = string("./")+path.substr(islash+1,idot-islash - 1) + ".xml";
|
||||
} else {
|
||||
ff = string("./")+path.substr(0,idot) + ".xml";
|
||||
}
|
||||
#ifdef DEBUG_PATHS
|
||||
cout << "get_XML_File(): Expected location of xml file = "
|
||||
<< ff << endl;
|
||||
#endif
|
||||
/*
|
||||
* Do a search of the existing XML trees to determine if we have
|
||||
* already processed this file. If we have, return a pointer to
|
||||
* the processed xml tree.
|
||||
*/
|
||||
if (xmlfiles.find(ff) != xmlfiles.end()) {
|
||||
#ifdef DEBUG_PATHS
|
||||
cout << "get_XML_File(): File, " << ff << ", was previously read."
|
||||
<< " Retrieving the stored xml tree." << endl;
|
||||
#endif
|
||||
return xmlfiles[ff];
|
||||
}
|
||||
/*
|
||||
* Ok, we didn't find the processed XML tree. Do the conversion
|
||||
* to xml, possibly overwriting the file, ff, in the process.
|
||||
*/
|
||||
ctml::ct2ctml(path.c_str(),debug);
|
||||
} else {
|
||||
ff = path;
|
||||
}
|
||||
/*
|
||||
* Take the XML file ff, open it, and process it, creating an
|
||||
* XML tree, and then adding an entry in the map. We will store
|
||||
* the absolute pathname as the key for this map.
|
||||
*/
|
||||
std::ifstream s(ff.c_str());
|
||||
|
||||
XML_Node* x = new XML_Node("doc");
|
||||
if (s) {
|
||||
x->build(s);
|
||||
x->lock();
|
||||
xmlfiles[ff] = x;
|
||||
} else {
|
||||
string estring = "cannot open "+ff+" for reading.";
|
||||
estring += "Note, this error indicates a possible configuration problem.";
|
||||
throw CanteraError("get_XML_File", estring);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the XML node pointer. At this point, we are sure that the
|
||||
* lookup operation in the return statement will return a valid
|
||||
* pointer.
|
||||
*/
|
||||
return xmlfiles[ff];
|
||||
}
|
||||
|
||||
|
||||
void Application::close_XML_File(std::string file)
|
||||
{
|
||||
XML_LOCK();
|
||||
if (file == "all") {
|
||||
std::map<string, XML_Node*>::iterator
|
||||
b = xmlfiles.begin(),
|
||||
e = xmlfiles.end();
|
||||
for (; b != e; ++b) {
|
||||
b->second->unlock();
|
||||
delete b->second;
|
||||
xmlfiles.erase(b->first);
|
||||
}
|
||||
} else if (xmlfiles.find(file) != xmlfiles.end()) {
|
||||
xmlfiles[file]->unlock();
|
||||
delete xmlfiles[file];
|
||||
xmlfiles.erase(file);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
long int Application::readStringRegistryKey(const std::string& keyName, const std::string& valueName,
|
||||
std::string& value, const std::string& defaultValue)
|
||||
{
|
||||
|
||||
HKEY key;
|
||||
long open_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_READ, &key);
|
||||
if (open_error != ERROR_SUCCESS) {
|
||||
return open_error;
|
||||
}
|
||||
value = defaultValue;
|
||||
CHAR buffer[1024];
|
||||
DWORD bufferSize = sizeof(buffer);
|
||||
ULONG error;
|
||||
error = RegQueryValueEx(key, valueName.c_str(), 0, NULL, (LPBYTE) buffer, &bufferSize);
|
||||
if (ERROR_SUCCESS == error) {
|
||||
value = buffer;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Application::setTmpDir(std::string tmp)
|
||||
{
|
||||
APP_LOCK();
|
||||
tmp_dir = tmp ;
|
||||
}
|
||||
|
||||
std::string Application::getTmpDir()
|
||||
{
|
||||
APP_LOCK();
|
||||
return tmp_dir ;
|
||||
}
|
||||
|
||||
std::string Application::sleep()
|
||||
{
|
||||
APP_LOCK();
|
||||
return m_sleep ;
|
||||
}
|
||||
|
||||
void Application::Messages::popError()
|
||||
{
|
||||
if (static_cast<int>(errorMessage.size()) > 0) {
|
||||
errorRoutine.pop_back() ;
|
||||
errorMessage.pop_back() ;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Application::Messages::lastErrorMessage()
|
||||
{
|
||||
if (static_cast<int>(errorMessage.size()) > 0) {
|
||||
string head =
|
||||
"\n\n************************************************\n"
|
||||
" Cantera Error! \n"
|
||||
"************************************************\n\n";
|
||||
return head+string("\nProcedure: ")+errorRoutine.back()
|
||||
+string("\nError: ")+errorMessage.back();
|
||||
} else {
|
||||
return "<no Cantera error>";
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Messages::getErrors(std::ostream& f)
|
||||
{
|
||||
int i = static_cast<int>(errorMessage.size());
|
||||
if (i == 0) {
|
||||
return;
|
||||
}
|
||||
f << endl << endl;
|
||||
f << "************************************************" << endl;
|
||||
f << " Cantera Error! " << endl;
|
||||
f << "************************************************" << endl
|
||||
<< endl;
|
||||
int j;
|
||||
for (j = 0; j < i; j++) {
|
||||
f << endl;
|
||||
f << "Procedure: " << errorRoutine[j] << endl;
|
||||
f << "Error: " << errorMessage[j] << endl;
|
||||
}
|
||||
f << endl << endl;
|
||||
errorMessage.clear();
|
||||
errorRoutine.clear();
|
||||
}
|
||||
|
||||
void Application::Messages::logErrors()
|
||||
{
|
||||
int i = static_cast<int>(errorMessage.size());
|
||||
if (i == 0) {
|
||||
return;
|
||||
}
|
||||
writelog("\n\n");
|
||||
writelog("************************************************\n");
|
||||
writelog(" Cantera Error! \n");
|
||||
writelog("************************************************\n\n");
|
||||
int j;
|
||||
for (j = 0; j < i; j++) {
|
||||
writelog("\n");
|
||||
writelog(string("Procedure: ")+ errorRoutine[j]+" \n");
|
||||
writelog(string("Error: ")+ errorMessage[j]+" \n");
|
||||
}
|
||||
writelog("\n\n");
|
||||
errorMessage.clear();
|
||||
errorRoutine.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Application::setDefaultDirectories()
|
||||
{
|
||||
std::vector<string>& dirs = inputDirs;
|
||||
|
||||
// always look in the local directory first
|
||||
dirs.push_back(".");
|
||||
|
||||
#ifdef _WIN32
|
||||
// Under Windows, the Cantera setup utility records the installation
|
||||
// directory in the registry. Data files are stored in the 'data' and
|
||||
// 'templates' subdirectories of the main installation directory.
|
||||
|
||||
std::string installDir;
|
||||
readStringRegistryKey("SOFTWARE\\Cantera\\Cantera 2.0", "InstallDir", installDir, "");
|
||||
if (installDir != "") {
|
||||
dirs.push_back(installDir + "data");
|
||||
dirs.push_back(installDir + "templates");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DARWIN
|
||||
//
|
||||
// add a default data location for Mac OS X
|
||||
//
|
||||
dirs.push_back("/Applications/Cantera/data");
|
||||
#endif
|
||||
|
||||
//
|
||||
// if environment variable CANTERA_DATA is defined, then add
|
||||
// it to the search path
|
||||
//
|
||||
if (getenv("CANTERA_DATA") != 0) {
|
||||
string datadir = string(getenv("CANTERA_DATA"));
|
||||
dirs.push_back(datadir);
|
||||
}
|
||||
|
||||
// CANTERA_DATA is defined in file config.h. This file is written
|
||||
// during the build process (unix), and points to the directory
|
||||
// specified by the 'prefix' option to 'configure', or else to
|
||||
// /usr/local/cantera.
|
||||
#ifdef CANTERA_DATA
|
||||
string datadir = string(CANTERA_DATA);
|
||||
dirs.push_back(datadir);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::addDataDirectory(std::string dir)
|
||||
{
|
||||
DIR_LOCK() ;
|
||||
if (inputDirs.size() == 0) {
|
||||
setDefaultDirectories();
|
||||
}
|
||||
string d = stripnonprint(dir);
|
||||
size_t m, n = inputDirs.size();
|
||||
|
||||
// don't add if already present
|
||||
for (m = 0; m < n; m++) {
|
||||
if (d == inputDirs[m]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
inputDirs.push_back(d);
|
||||
}
|
||||
|
||||
std::string Application::findInputFile(std::string name)
|
||||
{
|
||||
DIR_LOCK() ;
|
||||
string::size_type islash = name.find('/');
|
||||
string::size_type ibslash = name.find('\\');
|
||||
string inname;
|
||||
std::vector<string>& dirs = inputDirs;
|
||||
|
||||
int nd;
|
||||
if (islash == string::npos && ibslash == string::npos) {
|
||||
nd = static_cast<int>(dirs.size());
|
||||
int i;
|
||||
inname = "";
|
||||
for (i = 0; i < nd; i++) {
|
||||
inname = dirs[i] + "/" + name;
|
||||
std::ifstream fin(inname.c_str());
|
||||
if (fin) {
|
||||
fin.close();
|
||||
return inname;
|
||||
}
|
||||
}
|
||||
string msg;
|
||||
msg = "\nInput file " + name
|
||||
+ " not found in director";
|
||||
msg += (nd == 1 ? "y " : "ies ");
|
||||
for (i = 0; i < nd; i++) {
|
||||
msg += "\n'" + dirs[i] + "'";
|
||||
if (i < nd-1) {
|
||||
msg += ", ";
|
||||
}
|
||||
}
|
||||
msg += "\n\n";
|
||||
msg += "To fix this problem, either:\n";
|
||||
msg += " a) move the missing files into the local directory;\n";
|
||||
msg += " b) define environment variable CANTERA_DATA to\n";
|
||||
msg += " point to the directory containing the file.";
|
||||
throw CanteraError("findInputFile", msg);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
Application* Application::s_app = 0;
|
||||
|
||||
} // namespace Cantera
|
||||
787
src/base/application.h
Normal file
787
src/base/application.h
Normal file
|
|
@ -0,0 +1,787 @@
|
|||
#ifndef CT_BASE_APPLICATION_H
|
||||
#define CT_BASE_APPLICATION_H
|
||||
|
||||
#include "cantera/base/config.h"
|
||||
#include "cantera/base/logger.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
class XML_Node;
|
||||
|
||||
/*!
|
||||
* @defgroup globalData Global Data
|
||||
*
|
||||
* Global data are available anywhere. There are two kinds.
|
||||
* Cantera has an assortment of constant values for physical parameters.
|
||||
* Also, Cantera maintains a collection of global data which is specific
|
||||
* to each process that invokes Cantera functions. This process-specific
|
||||
* data is stored in the class Application.
|
||||
*/
|
||||
|
||||
|
||||
//! Class to hold global data.
|
||||
/*!
|
||||
* Class Application is the top-level
|
||||
* class that stores data that should persist for the duration of
|
||||
* the process. The class should not be instantiated directly;
|
||||
* instead, it is instantiated as needed by the functions declared
|
||||
* here. At most one instance is created, and it is not destroyed
|
||||
* until the process terminates.
|
||||
*
|
||||
* @ingroup HTML_logs
|
||||
* @ingroup textlogs
|
||||
* @ingroup globalData
|
||||
*/
|
||||
class Application
|
||||
{
|
||||
protected:
|
||||
//! Class to carry out messages
|
||||
/*!
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
class Messages
|
||||
{
|
||||
public:
|
||||
//! Constructor for the Messages class
|
||||
/*! Constructor for the Messages class which is a subclass
|
||||
* of the Application class.
|
||||
*/
|
||||
Messages();
|
||||
|
||||
//! Copy Constructor for the Messages class
|
||||
/*! Constructor for the Messages class which is a subclass
|
||||
* of the Application class.
|
||||
* @param r Message to be copied
|
||||
*/
|
||||
Messages(const Messages& r);
|
||||
|
||||
//! Assignment operator
|
||||
/*!
|
||||
* @param r Message to be copied
|
||||
*/
|
||||
Messages& operator=(const Messages& r);
|
||||
|
||||
//! Destructor for the Messages class
|
||||
~Messages();
|
||||
|
||||
//! Set an error condition in the application class without
|
||||
//! throwing an exception.
|
||||
/*!
|
||||
* This routine adds an error message to the end of the stack
|
||||
* of errors that Cantera accumulates in the Application
|
||||
* class.
|
||||
* @param r location
|
||||
* @param msg Description of the error
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
void addError(std::string r, std::string msg);
|
||||
|
||||
//! Return the number of errors that have been encountered so far.
|
||||
/*!
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
int getErrorCount() ;
|
||||
|
||||
//! Discard the last error message
|
||||
/*!
|
||||
* %Cantera saves a stack of exceptions that it
|
||||
* has caught in the Application class. This routine eliminates
|
||||
* the last exception to be added to that stack.
|
||||
*
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
void popError() ;
|
||||
|
||||
//! Retrieve the last error message in a string
|
||||
/*!
|
||||
* This routine will retrieve the last error message and return
|
||||
* it in the return string.
|
||||
*
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
std::string lastErrorMessage() ;
|
||||
|
||||
//! Prints all of the error messages to an ostream
|
||||
/*!
|
||||
* Print all of the error messages using function writelog.
|
||||
* Write out all of the saved error messages to the ostream f
|
||||
* Cantera saves a stack of exceptions that it
|
||||
* has caught in the Application class. This routine writes
|
||||
* out all of the error messages to the ostream
|
||||
* and then clears them from internal storage.
|
||||
*
|
||||
* @param f ostream which will receive the error messages
|
||||
*
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
void getErrors(std::ostream& f) ;
|
||||
|
||||
//! Prints all of the error messages using writelog
|
||||
/*!
|
||||
* Print all of the error messages using function writelog.
|
||||
* Cantera saves a stack of exceptions that it
|
||||
* has caught in the Application class. This routine writes
|
||||
* out all of the error messages
|
||||
* and then clears them from internal storage.
|
||||
*
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
void logErrors();
|
||||
|
||||
//! Write a message to the screen.
|
||||
/*!
|
||||
* The string may be of any
|
||||
* length, and may contain end-of-line characters. This method is
|
||||
* used throughout %Cantera to write log messages.
|
||||
*
|
||||
* @param msg c++ string to be written to the screen
|
||||
* @ingroup textlogs
|
||||
*/
|
||||
void writelog(const std::string& msg);
|
||||
|
||||
//! Write an end of line and flush output
|
||||
void writelogendl();
|
||||
|
||||
//! Write a message to the screen.
|
||||
/*!
|
||||
* The string may be of any
|
||||
* length, and may contain end-of-line characters. This method is
|
||||
* used throughout %Cantera to write log messages.
|
||||
*
|
||||
* @param pszmsg c character string to be written to the screen
|
||||
* @ingroup textlogs
|
||||
*/
|
||||
void writelog(const char* pszmsg) ;
|
||||
|
||||
//! Write an error message and quit.
|
||||
/*!
|
||||
* The default behavior is
|
||||
* to write to the standard error stream, and then call
|
||||
* exit(). Note that no end-of-line character is appended to
|
||||
* the message, and so if one is desired it must be included
|
||||
* in the string. Note that this default behavior will
|
||||
* terminate the application Cantera is invoked from (MATLAB,
|
||||
* Excel, etc.) If this is not desired, then derive a class
|
||||
* and reimplement this method.
|
||||
*
|
||||
* @param msg Error message to be written to cerr.
|
||||
*/
|
||||
void logerror(const std::string& msg) ;
|
||||
|
||||
//! Returns an integer specifying the application environment
|
||||
int getUserEnv() ;
|
||||
|
||||
//! Install a logger.
|
||||
/*!
|
||||
* Called by the language interfaces to install an appropriate logger.
|
||||
* The logger is used for the writelog() function
|
||||
*
|
||||
* @param logwriter Pointer to a logger object
|
||||
* @see Logger.
|
||||
* @ingroup textlogs
|
||||
*/
|
||||
void setLogger(Logger* logwriter) ;
|
||||
|
||||
#ifdef WITH_HTML_LOGS
|
||||
|
||||
//!Create a new group for log messages.
|
||||
/*!
|
||||
* Usually this is called
|
||||
* upon entering the function, with the title parameter equal to
|
||||
* the name of the function or method. Subsequent messages
|
||||
* written with addLogEntry will appear grouped under this
|
||||
* heading, until endLogGroup() is called.
|
||||
*
|
||||
* @param title String name of the LogGroup
|
||||
* @param loglevel loglevel of the group.
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void beginLogGroup(std::string title, int loglevel) ;
|
||||
|
||||
//! Add an entry to an HTML log file.
|
||||
/*!
|
||||
* Entries appear in the form "tag:value".
|
||||
*
|
||||
* @param tag tag
|
||||
* @param value double value
|
||||
*
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void addLogEntry(std::string tag, std::string value) ;
|
||||
|
||||
//! Add an entry to an HTML log file.
|
||||
/*!
|
||||
* Entries appear in the form "tag:value".
|
||||
*
|
||||
* @param tag tag
|
||||
* @param value double value
|
||||
*
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void addLogEntry(std::string tag, doublereal value) ;
|
||||
|
||||
//! Add an entry to an HTML log file.
|
||||
/*!
|
||||
* Entries appear in the form "tag:value".
|
||||
*
|
||||
* @param tag tag
|
||||
* @param value double value
|
||||
*
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void addLogEntry(std::string tag, int value) ;
|
||||
|
||||
//! Add an entry to an HTML log file.
|
||||
/*!
|
||||
* Entries appear in the form "msg".
|
||||
*
|
||||
* @param msg Message to be added
|
||||
*
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void addLogEntry(std::string msg) ;
|
||||
|
||||
//! Close the current group of log messages.
|
||||
/*!
|
||||
* This is typically
|
||||
* called just before leaving a function or method, to close the
|
||||
* group of messages that were output from this
|
||||
* function. Subsequent messages written with addLogEntry() will
|
||||
* appear at the next-higher level in the outline, unless
|
||||
* beginLogGroup() is called first to create a new group.
|
||||
*
|
||||
* @param title Name of the log group. It defaults to the most recent
|
||||
* log group created.
|
||||
*/
|
||||
void endLogGroup(std::string title) ;
|
||||
|
||||
//! Write the HTML log file.
|
||||
/*!
|
||||
* Log entries are stored in memory in
|
||||
* an XML tree until this function is called, which writes the
|
||||
* tree to a file and clears the entries stored in memory. The
|
||||
* output file will have the name specified in the 'file'
|
||||
* argument. If this argument has no extension, the extension
|
||||
* '.html' will be appended. Also, if the file already exists, an
|
||||
* integer will be appended to the name so that no existing log
|
||||
* file will be overwritten.
|
||||
* WITH_HTML_LOGS must be defined.
|
||||
*
|
||||
* @param file Name of the file to be written
|
||||
*/
|
||||
void write_logfile(std::string file);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
//! Current list of error messages
|
||||
std::vector<std::string> errorMessage;
|
||||
|
||||
//! Current error Routine
|
||||
std::vector<std::string> errorRoutine;
|
||||
|
||||
//! Current pointer to the logwriter
|
||||
Logger* logwriter;
|
||||
#ifdef WITH_HTML_LOGS
|
||||
//! Current pointer to the top of the XML_Node tree for the current HTML log
|
||||
XML_Node* xmllog;
|
||||
|
||||
//! Pointer to the last current position in the XML_Node tree for the current HTML log
|
||||
XML_Node* current;
|
||||
|
||||
//! Current value of the loglevel
|
||||
int loglevel;
|
||||
|
||||
//! Vector of loglevels for loggroups that are open
|
||||
std::vector<int> loglevels;
|
||||
|
||||
//! Current vector of loggroups that are open
|
||||
std::vector<std::string> loggroups;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
#ifdef THREAD_SAFE_CANTERA
|
||||
//! Typedef for thread specific messages
|
||||
typedef boost::shared_ptr< Messages > pMessages_t ;
|
||||
|
||||
//! Typedef for map between a thread and the message
|
||||
typedef std::map< cthreadId_t, pMessages_t > threadMsgMap_t ;
|
||||
|
||||
//! Class that stores thread messages for each thread, and retrieves them
|
||||
//! based on the thread id.
|
||||
class ThreadMessages
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
ThreadMessages() {
|
||||
}
|
||||
|
||||
//! Provide a pointer deferencing overloaded operator
|
||||
/*!
|
||||
* @return returns a pointer to Messages
|
||||
*/
|
||||
Messages* operator->() {
|
||||
MSG_LOCK() ;
|
||||
cthreadId_t curId = getThisThreadId() ;
|
||||
threadMsgMap_t::iterator iter = m_threadMsgMap.find(curId) ;
|
||||
if (iter != m_threadMsgMap.end()) {
|
||||
return (iter->second.get()) ;
|
||||
}
|
||||
pMessages_t pMsgs(new Messages()) ;
|
||||
m_threadMsgMap.insert(std::pair< cthreadId_t, pMessages_t >(curId, pMsgs)) ;
|
||||
return pMsgs.get() ;
|
||||
}
|
||||
|
||||
//! Remove a local thread message
|
||||
void removeThreadMessages() {
|
||||
MSG_LOCK() ;
|
||||
cthreadId_t curId = getThisThreadId() ;
|
||||
threadMsgMap_t::iterator iter = m_threadMsgMap.find(curId) ;
|
||||
if (iter != m_threadMsgMap.end()) {
|
||||
m_threadMsgMap.erase(iter) ;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//! Thread Msg Map
|
||||
threadMsgMap_t m_threadMsgMap ;
|
||||
} ;
|
||||
#endif
|
||||
|
||||
|
||||
protected:
|
||||
//! Constructor for class sets up the initial conditions
|
||||
//! Protected ctor access thru static member function Instance
|
||||
Application();
|
||||
|
||||
public:
|
||||
//! Return a pointer to the one and only instance of class Application
|
||||
/*!
|
||||
* If the an Application object has not yet been created it is created
|
||||
*/
|
||||
static Application* Instance();
|
||||
|
||||
//! Destructor for class deletes global data
|
||||
/*!
|
||||
* Delete any open XML trees, the logwriter, and
|
||||
* the XML log, if any.
|
||||
*/
|
||||
virtual ~Application();
|
||||
|
||||
//! Static function that destroys the application class's data
|
||||
static void ApplicationDestroy();
|
||||
|
||||
//! Set the directory where temporary files may be written.
|
||||
/*!
|
||||
* @param tmp Name of the directory
|
||||
*/
|
||||
void setTmpDir(std::string tmp) ;
|
||||
|
||||
//! get the name of a directory where temporary files may be written.
|
||||
std::string getTmpDir() ;
|
||||
|
||||
//! Pause the application for a certain amount
|
||||
/*!
|
||||
* This has been needed in the past for some network file systems.
|
||||
*/
|
||||
std::string sleep() ;
|
||||
|
||||
//! Set an error condition in the application class without
|
||||
//! throwing an exception.
|
||||
/*!
|
||||
* This routine adds an error message to the end of the stack
|
||||
* of errors that Cantera accumulates in the Application
|
||||
* class.
|
||||
* @param r location
|
||||
* @param msg Description of the error
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
void addError(std::string r, std::string msg) {
|
||||
pMessenger->addError(r, msg) ;
|
||||
}
|
||||
|
||||
//! Return the number of errors that have been encountered so far.
|
||||
/*!
|
||||
* @ingroup error handling
|
||||
*/
|
||||
int getErrorCount() {
|
||||
return pMessenger->getErrorCount() ;
|
||||
}
|
||||
|
||||
//! Discard the last error message
|
||||
/*!
|
||||
* %Cantera saves a stack of exceptions that it
|
||||
* has caught in the Application class. This routine eliminates
|
||||
* the last exception to be added to that stack.
|
||||
*
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
void popError() {
|
||||
pMessenger->popError() ;
|
||||
}
|
||||
|
||||
//! Retrieve the last error message in a string
|
||||
/*!
|
||||
* This routine will retrieve the last error message and return
|
||||
* it in the return string.
|
||||
*
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
std::string lastErrorMessage() {
|
||||
return pMessenger->lastErrorMessage() ;
|
||||
}
|
||||
|
||||
//! Prints all of the error messages to an ostream
|
||||
/*!
|
||||
* Print all of the error messages using function writelog.
|
||||
* Write out all of the saved error messages to the ostream f
|
||||
* Cantera saves a stack of exceptions that it
|
||||
* has caught in the Application class. This routine writes
|
||||
* out all of the error messages to the ostream
|
||||
* and then clears them from internal storage.
|
||||
*
|
||||
* @param f ostream which will receive the error messages
|
||||
*
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
void getErrors(std::ostream& f) {
|
||||
pMessenger->getErrors(f) ;
|
||||
}
|
||||
|
||||
//! Prints all of the error messages using writelog
|
||||
/*!
|
||||
* Print all of the error messages using function writelog.
|
||||
* Cantera saves a stack of exceptions that it
|
||||
* has caught in the Application class. This routine writes
|
||||
* out all of the error messages
|
||||
* and then clears them from internal storage.
|
||||
*
|
||||
* @ingroup errorhandling
|
||||
*/
|
||||
void logErrors() {
|
||||
pMessenger->logErrors() ;
|
||||
}
|
||||
|
||||
//! Add a directory to the data file search path.
|
||||
/*!
|
||||
* @ingroup inputfiles
|
||||
*
|
||||
* @param dir String name for the directory to be added to the search path
|
||||
*/
|
||||
void addDataDirectory(std::string dir) ;
|
||||
|
||||
//! Find an input file.
|
||||
/*!
|
||||
* This routine will search for a file in the default
|
||||
* locations specified for the application.
|
||||
* See the routine setDefaultDirectories() listed above.
|
||||
*
|
||||
* The default set of directories specified for the application
|
||||
* will be searched if a '/' or an '\\' is found in the
|
||||
* name. If either is found then a relative path name is
|
||||
* presumed, and the default directories are not searched.
|
||||
*
|
||||
* The presence of the file is determined by whether the file
|
||||
* can be opened for reading by the current user.
|
||||
*
|
||||
* @param name Name of the input file to be searched for
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The absolute path name of the first matching
|
||||
* file is returned. If a relative path name
|
||||
* is indicated, the relative path name is returned.
|
||||
*
|
||||
* If the file is not found, a message is written to
|
||||
* stdout and a CanteraError exception is thrown.
|
||||
*
|
||||
* @ingroup inputfiles
|
||||
*/
|
||||
std::string findInputFile(std::string name) ;
|
||||
|
||||
//! Return a pointer to the XML tree for a Cantera input file.
|
||||
/*!
|
||||
* This routine will find the file and read the XML file into an
|
||||
* XML tree structure. Then, a pointer will be returned. If the
|
||||
* file has already been processed, then just the pointer will
|
||||
* be returned.
|
||||
*
|
||||
* @param file String containing the relative or absolute file name
|
||||
* @param debug Debug flag
|
||||
*/
|
||||
XML_Node* get_XML_File(std::string file, int debug=0) ;
|
||||
|
||||
//! Close an XML File
|
||||
/*!
|
||||
* Close a file that is opened by this application object
|
||||
*
|
||||
* @param file String containing the relative or absolute file name
|
||||
*/
|
||||
void close_XML_File(std::string file) ;
|
||||
|
||||
//! Write a message to the screen.
|
||||
/*!
|
||||
* The string may be of any
|
||||
* length, and may contain end-of-line characters. This method is
|
||||
* used throughout %Cantera to write log messages.
|
||||
*
|
||||
* @param msg c++ string to be written to the screen
|
||||
* @ingroup textlogs
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
long int readStringRegistryKey(const std::string& keyName, const std::string& valueName,
|
||||
std::string& value, const std::string& defaultValue);
|
||||
#endif
|
||||
|
||||
void writelog(const std::string& msg) {
|
||||
pMessenger->writelog(msg);
|
||||
}
|
||||
|
||||
|
||||
//! Write an endl to the screen and flush output
|
||||
/*!
|
||||
* @ingroup textlogs
|
||||
*/
|
||||
void writelogendl() {
|
||||
pMessenger->writelogendl();
|
||||
}
|
||||
|
||||
//! Write a message to the screen.
|
||||
/*!
|
||||
* The string may be of any
|
||||
* length, and may contain end-of-line characters. This method is
|
||||
* used throughout %Cantera to write log messages.
|
||||
*
|
||||
* @param pszmsg c null terminated string to be written to the screen
|
||||
* @ingroup textlogs
|
||||
*/
|
||||
void writelog(const char* pszmsg) {
|
||||
pMessenger->writelog(pszmsg);
|
||||
}
|
||||
|
||||
//! Write an error message and quit.
|
||||
/*!
|
||||
* The default behavior is
|
||||
* to write to the standard error stream, and then call
|
||||
* exit(). Note that no end-of-line character is appended to
|
||||
* the message, and so if one is desired it must be included
|
||||
* in the string. Note that this default behavior will
|
||||
* terminate the application Cantera is invoked from (MATLAB,
|
||||
* Excel, etc.) If this is not desired, then derive a class
|
||||
* and reimplement this method.
|
||||
*
|
||||
* @param msg Error message to be written to cerr.
|
||||
*/
|
||||
void logerror(const std::string& msg) {
|
||||
pMessenger->logerror(msg);
|
||||
}
|
||||
|
||||
//! Returns an integer specifying the application environment.
|
||||
int getUserEnv() {
|
||||
return pMessenger->getUserEnv() ;
|
||||
}
|
||||
|
||||
//! Install a logger - Called by the language interfaces to install an
|
||||
//! appropriate logger.
|
||||
/*!
|
||||
* @param logwriter Pointer to a logger object
|
||||
* @see Logger.
|
||||
* @ingroup textlogs
|
||||
*/
|
||||
void setLogger(Logger* logwriter) {
|
||||
pMessenger->setLogger(logwriter);
|
||||
}
|
||||
|
||||
//! Delete Messenger object allocated per thread.
|
||||
void thread_complete() ;
|
||||
|
||||
#ifdef WITH_HTML_LOGS
|
||||
//!Create a new group for log messages.
|
||||
/*!
|
||||
* Usually this is called
|
||||
* upon entering the function, with the title parameter equal to
|
||||
* the name of the function or method. Subsequent messages
|
||||
* written with addLogEntry will appear grouped under this
|
||||
* heading, until endLogGroup() is called.
|
||||
*
|
||||
* @param title String name of the LogGroup
|
||||
* @param loglevel loglevel of the group.
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void beginLogGroup(std::string title, int loglevel) {
|
||||
pMessenger->beginLogGroup(title,loglevel);
|
||||
}
|
||||
|
||||
//! Add an entry to an HTML log file.
|
||||
/*!
|
||||
* Entries appear in the form "tag:value".
|
||||
*
|
||||
* @param tag tag
|
||||
* @param value double value
|
||||
*
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void addLogEntry(std::string tag, std::string value) {
|
||||
pMessenger->addLogEntry(tag, value);
|
||||
}
|
||||
|
||||
//! Add an entry to an HTML log file.
|
||||
/*!
|
||||
* Entries appear in the form "tag:value".
|
||||
*
|
||||
* @param tag tag
|
||||
* @param value double value
|
||||
*
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void addLogEntry(std::string tag, doublereal value) {
|
||||
pMessenger->addLogEntry(tag, value);
|
||||
}
|
||||
|
||||
//! Add an entry to an HTML log file.
|
||||
/*!
|
||||
* Entries appear in the form "tag:value".
|
||||
*
|
||||
* @param tag tag
|
||||
* @param value double value
|
||||
*
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void addLogEntry(std::string tag, int value) {
|
||||
pMessenger->addLogEntry(tag, value);
|
||||
}
|
||||
|
||||
//! Add an entry to an HTML log file.
|
||||
/*!
|
||||
* Entries appear in the form "msg".
|
||||
*
|
||||
* @param msg Message to be added to file
|
||||
*
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void addLogEntry(std::string msg) {
|
||||
pMessenger->addLogEntry(msg);
|
||||
}
|
||||
|
||||
//! Close the current group of log messages.
|
||||
/*!
|
||||
* This is typically
|
||||
* called just before leaving a function or method, to close the
|
||||
* group of messages that were output from this
|
||||
* function. Subsequent messages written with addLogEntry() will
|
||||
* appear at the next-higher level in the outline, unless
|
||||
* beginLogGroup() is called first to create a new group.
|
||||
*
|
||||
* @param title Name of the log group. It defaults to the most recent
|
||||
* log group created.
|
||||
* @ingroup HTML_logs
|
||||
*/
|
||||
void endLogGroup(std::string title) {
|
||||
pMessenger->endLogGroup(title) ;
|
||||
}
|
||||
|
||||
//! Write the HTML log file.
|
||||
/*!
|
||||
* Log entries are stored in memory in
|
||||
* an XML tree until this function is called, which writes the
|
||||
* tree to a file and clears the entries stored in memory. The
|
||||
* output file will have the name specified in the 'file'
|
||||
* argument. If this argument has no extension, the extension
|
||||
* '.html' will be appended. Also, if the file already exists, an
|
||||
* integer will be appended to the name so that no existing log
|
||||
* file will be overwritten.
|
||||
* WITH_HTML_LOGS must be defined.
|
||||
*
|
||||
* @param file Name of the file to be written
|
||||
*/
|
||||
void write_logfile(std::string file) {
|
||||
pMessenger->write_logfile(file) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
//! Set the default directories for input files.
|
||||
/*!
|
||||
* %Cantera searches
|
||||
* for input files along a path that includes platform-specific
|
||||
* default locations, and possibly user-specified locations. This
|
||||
* function installs the platform-specific directories on the
|
||||
* search path. It is invoked at startup by appinit(), and never
|
||||
* should need to be called by user programs.
|
||||
*
|
||||
* The current directory (".") is always searched first. Then, on
|
||||
* Windows platforms, if environment variable COMMONPROGRAMFILES
|
||||
* is set (which it should be on Win XP or Win 2000), then
|
||||
* directories under this one will be added to the search
|
||||
* path. The %Cantera Windows installer installs data files to this
|
||||
* location.
|
||||
*
|
||||
* On the Mac, directory '/Applications/Cantera/data' is added to the
|
||||
* search path.
|
||||
*
|
||||
* On any platform, if environment variable CANTERA_DATA is set to a
|
||||
* directory name, then this directory is added to the search path.
|
||||
*
|
||||
* Finally, the location where the data files were installed when
|
||||
* %Cantera was built is added to the search path.
|
||||
*
|
||||
* Additional directories may be added by calling function addDirectory.
|
||||
* @ingroup inputfiles
|
||||
*/
|
||||
void setDefaultDirectories();
|
||||
|
||||
//! Current vector of input directories to search for input files
|
||||
std::vector<std::string> inputDirs;
|
||||
//! Current list of error messages
|
||||
//vector<string> errorMessage;
|
||||
//! Current list of warning messages
|
||||
//vector<string> warning;
|
||||
//! Current error Routine
|
||||
//vector<string> errorRoutine;
|
||||
//! Last error message
|
||||
//string msglog;
|
||||
//! Current line length
|
||||
// size_t linelen;
|
||||
//! Current value of stop_on_error
|
||||
bool stop_on_error;
|
||||
//! Current map of options
|
||||
std::map<std::string, std::string> options;
|
||||
//! Current value of tmp_dir
|
||||
std::string tmp_dir;
|
||||
//! Current vector of xml file trees that have been previously parsed
|
||||
std::map<std::string, XML_Node*> xmlfiles;
|
||||
//! Current sleep command.
|
||||
std::string m_sleep;
|
||||
//! Current pointer to the logwriter
|
||||
//Logger* logwriter;
|
||||
#ifdef WITH_HTML_LOGS
|
||||
//! Current pointer to the top of the XML_Node tree for the current HTML log
|
||||
//XML_Node *xmllog;
|
||||
//! Pointer to the last current position in the XML_Node tree for the current HTML log
|
||||
//XML_Node *current;
|
||||
//! Current value of loglevel
|
||||
//int loglevel;
|
||||
//! Vector of loglevels for loggroups that are open
|
||||
//vector<int> loglevels;
|
||||
//! Current vector of loggroups that are open
|
||||
//vector<string> loggroups;
|
||||
#endif
|
||||
|
||||
#if defined(THREAD_SAFE_CANTERA)
|
||||
ThreadMessages pMessenger ;
|
||||
#else
|
||||
std::auto_ptr<Messages> pMessenger ;
|
||||
#endif
|
||||
|
||||
private:
|
||||
//! Pointer to the single Application instance
|
||||
static Application* s_app ;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
48
src/base/ctexceptions.cpp
Normal file
48
src/base/ctexceptions.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include "cantera/base/ctexceptions.h"
|
||||
|
||||
#include "application.h"
|
||||
#include "cantera/base/global.h"
|
||||
#include "cantera/base/stringUtils.h"
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
// *** Exceptions ***
|
||||
|
||||
CanteraError::CanteraError(std::string procedure, std::string msg)
|
||||
{
|
||||
Application::Instance()->addError(procedure, msg);
|
||||
}
|
||||
|
||||
ArraySizeError::ArraySizeError(std::string proc, size_t sz, size_t reqd) :
|
||||
CanteraError(proc, "Array size ("+int2str(sz)+
|
||||
") too small. Must be at least "+int2str(reqd))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ElementRangeError::ElementRangeError(std::string func, size_t m, size_t mmax) :
|
||||
CanteraError(func, "Element index " + int2str(m) +
|
||||
" outside valid range of 0 to " + int2str(mmax-1))
|
||||
{
|
||||
}
|
||||
|
||||
// *** Warnings ***
|
||||
|
||||
void deprecatedMethod(std::string classnm, std::string oldnm, std::string newnm)
|
||||
{
|
||||
writelog(">>>> WARNING: method "+oldnm+" of class "+classnm
|
||||
+" is deprecated.\n");
|
||||
writelog(" Use method "+newnm+" instead.\n");
|
||||
writelog(" (If you want to rescue this method from deprecated\n");
|
||||
writelog(" status, see http://www.cantera.org/deprecated.html)");
|
||||
}
|
||||
|
||||
void removeAtVersion(std::string func, std::string version)
|
||||
{
|
||||
writelog("Removed procedure: "+func+"\n");
|
||||
writelog("Removed in version: "+version+"\n");
|
||||
throw CanteraError("removeAtVersion: "+ func,"procedure has been removed.");
|
||||
}
|
||||
|
||||
|
||||
} // namespace Cantera
|
||||
303
src/base/global.cpp
Normal file
303
src/base/global.cpp
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
#include "cantera/base/global.h"
|
||||
|
||||
#include "cantera/base/ctexceptions.h"
|
||||
#include "cantera/base/FactoryBase.h"
|
||||
#include "cantera/base/xml.h"
|
||||
#include "application.h"
|
||||
#include "units.h"
|
||||
|
||||
// RFB:TODO May need OS specifc include to use varargs.h instead
|
||||
#include <stdarg.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Cantera {
|
||||
|
||||
//! Return a pointer to the application object
|
||||
static Application* app()
|
||||
{
|
||||
return Application::Instance() ;
|
||||
}
|
||||
|
||||
// **************** Text Logging ****************
|
||||
|
||||
void setLogger(Logger* logwriter)
|
||||
{
|
||||
try {
|
||||
app()->setLogger(logwriter) ;
|
||||
} catch (std::bad_alloc) {
|
||||
logwriter->error("bad alloc thrown by app()");
|
||||
}
|
||||
}
|
||||
|
||||
void writelog(const std::string& msg)
|
||||
{
|
||||
app()->writelog(msg);
|
||||
}
|
||||
|
||||
void writelog(const char* msg)
|
||||
{
|
||||
app()->writelog(msg);
|
||||
}
|
||||
|
||||
void writelogf(const char* fmt,...)
|
||||
{
|
||||
enum { BUFSIZE = 2048 } ;
|
||||
char sbuf[BUFSIZE] ;
|
||||
|
||||
va_list args ;
|
||||
va_start(args, fmt) ;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_vsnprintf(sbuf, BUFSIZE, fmt, args) ;
|
||||
#else
|
||||
vsprintf(sbuf, fmt, args) ;
|
||||
#endif
|
||||
|
||||
writelog(sbuf) ;
|
||||
va_end(args) ;
|
||||
}
|
||||
|
||||
void writelogendl()
|
||||
{
|
||||
app()->writelogendl();
|
||||
}
|
||||
|
||||
void error(const std::string& msg)
|
||||
{
|
||||
app()->logerror(msg);
|
||||
}
|
||||
|
||||
int userInterface()
|
||||
{
|
||||
return app()->getUserEnv();
|
||||
}
|
||||
|
||||
// **************** HTML Logging ****************
|
||||
|
||||
#ifdef WITH_HTML_LOGS
|
||||
|
||||
void beginLogGroup(std::string title, int loglevel)
|
||||
{
|
||||
app()->beginLogGroup(title, loglevel) ;
|
||||
}
|
||||
|
||||
void addLogEntry(std::string tag, std::string value)
|
||||
{
|
||||
app()->addLogEntry(tag, value) ;
|
||||
}
|
||||
|
||||
void addLogEntry(std::string tag, doublereal value)
|
||||
{
|
||||
app()->addLogEntry(tag, value) ;
|
||||
}
|
||||
|
||||
void addLogEntry(std::string tag, int value)
|
||||
{
|
||||
app()->addLogEntry(tag, value) ;
|
||||
}
|
||||
|
||||
void addLogEntry(std::string msg)
|
||||
{
|
||||
app()->addLogEntry(msg) ;
|
||||
}
|
||||
|
||||
void endLogGroup(std::string title)
|
||||
{
|
||||
app()->endLogGroup(title) ;
|
||||
}
|
||||
|
||||
void write_logfile(std::string file)
|
||||
{
|
||||
app()->write_logfile(file) ;
|
||||
}
|
||||
|
||||
#endif // WITH_HTML_LOGS
|
||||
|
||||
// **************** Global Data ****************
|
||||
|
||||
Unit* Unit::s_u = 0;
|
||||
|
||||
#if defined(THREAD_SAFE_CANTERA)
|
||||
boost::mutex Unit::units_mutex ;
|
||||
#endif
|
||||
|
||||
void appdelete()
|
||||
{
|
||||
Application::ApplicationDestroy() ;
|
||||
FactoryBase::deleteFactories();
|
||||
Unit::deleteUnit();
|
||||
}
|
||||
|
||||
void thread_complete()
|
||||
{
|
||||
app()->thread_complete() ;
|
||||
}
|
||||
|
||||
XML_Node* get_XML_File(std::string file, int debug)
|
||||
{
|
||||
XML_Node* xtmp = app()->get_XML_File(file, debug) ;
|
||||
//writelog("get_XML_File: returned from app:get_XML_FILE " + int2str(xtmp) + "\n");
|
||||
return xtmp;
|
||||
}
|
||||
|
||||
void close_XML_File(std::string file)
|
||||
{
|
||||
app()->close_XML_File(file) ;
|
||||
}
|
||||
|
||||
void setTmpDir(std::string tmp)
|
||||
{
|
||||
app()->setTmpDir(tmp);
|
||||
}
|
||||
|
||||
string tmpDir()
|
||||
{
|
||||
return app()->getTmpDir();
|
||||
}
|
||||
|
||||
string sleep()
|
||||
{
|
||||
return app()->sleep();
|
||||
}
|
||||
|
||||
int nErrors()
|
||||
{
|
||||
return app()->getErrorCount();
|
||||
}
|
||||
|
||||
void popError()
|
||||
{
|
||||
app()->popError() ;
|
||||
}
|
||||
|
||||
string lastErrorMessage()
|
||||
{
|
||||
return app()->lastErrorMessage() ;
|
||||
}
|
||||
|
||||
void showErrors(std::ostream& f)
|
||||
{
|
||||
app()->getErrors(f) ;
|
||||
}
|
||||
|
||||
void showErrors()
|
||||
{
|
||||
app()->logErrors() ;
|
||||
}
|
||||
|
||||
void setError(std::string r, std::string msg)
|
||||
{
|
||||
app()->addError(r, msg) ;
|
||||
}
|
||||
|
||||
void addDirectory(std::string dir)
|
||||
{
|
||||
app()->addDataDirectory(dir) ;
|
||||
}
|
||||
|
||||
std::string findInputFile(std::string name)
|
||||
{
|
||||
return app()->findInputFile(name) ;
|
||||
}
|
||||
|
||||
doublereal toSI(std::string unit)
|
||||
{
|
||||
doublereal f = Unit::units()->toSI(unit);
|
||||
if (f) {
|
||||
return f;
|
||||
} else {
|
||||
throw CanteraError("toSI","unknown unit string: "+unit);
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
doublereal actEnergyToSI(std::string unit)
|
||||
{
|
||||
doublereal f = Unit::units()->actEnergyToSI(unit);
|
||||
if (f) {
|
||||
return f;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
string canteraRoot()
|
||||
{
|
||||
char* ctroot = 0;
|
||||
ctroot = getenv("CANTERA_ROOT");
|
||||
if (ctroot != 0) {
|
||||
return string(ctroot);
|
||||
}
|
||||
#ifdef CANTERA_ROOT
|
||||
return string(CANTERA_ROOT);
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//! split a string at a '#' sign. Used to separate a file name from an id string.
|
||||
/*!
|
||||
* @param src Original string to be split up. This is unchanged.
|
||||
* @param file Output string representing the first part of the string, which is the filename.
|
||||
* @param id Output string representing the last part of the string, which is the id.
|
||||
*/
|
||||
static void split_at_pound(const std::string& src, std::string& file, std::string& id)
|
||||
{
|
||||
string::size_type ipound = src.find('#');
|
||||
if (ipound != string::npos) {
|
||||
id = src.substr(ipound+1,src.size());
|
||||
file = src.substr(0,ipound);
|
||||
} else {
|
||||
id = "";
|
||||
file = src;
|
||||
}
|
||||
}
|
||||
|
||||
XML_Node* get_XML_Node(const std::string& file_ID, XML_Node* root)
|
||||
{
|
||||
std::string fname, idstr;
|
||||
XML_Node* db, *doc;
|
||||
split_at_pound(file_ID, fname, idstr);
|
||||
if (fname == "") {
|
||||
if (!root) throw CanteraError("get_XML_Node",
|
||||
"no file name given. file_ID = "+file_ID);
|
||||
db = root->findID(idstr, 3);
|
||||
} else {
|
||||
doc = get_XML_File(fname);
|
||||
if (!doc) throw CanteraError("get_XML_Node",
|
||||
"get_XML_File failed trying to open "+fname);
|
||||
db = doc->findID(idstr, 3);
|
||||
}
|
||||
if (!db) {
|
||||
throw CanteraError("get_XML_Node",
|
||||
"id tag '"+idstr+"' not found.");
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
XML_Node* get_XML_NameID(const std::string& nameTarget,
|
||||
const std::string& file_ID,
|
||||
XML_Node* root)
|
||||
{
|
||||
string fname, idTarget;
|
||||
XML_Node* db, *doc;
|
||||
split_at_pound(file_ID, fname, idTarget);
|
||||
if (fname == "") {
|
||||
if (!root) {
|
||||
return 0;
|
||||
}
|
||||
db = root->findNameID(nameTarget, idTarget);
|
||||
} else {
|
||||
doc = get_XML_File(fname);
|
||||
if (!doc) {
|
||||
return 0;
|
||||
}
|
||||
db = doc->findNameID(nameTarget, idTarget);
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
std::vector<FactoryBase*> FactoryBase::s_vFactoryRegistry;
|
||||
|
||||
}
|
||||
2153
src/base/misc.cpp
2153
src/base/misc.cpp
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue