26 #pragma comment(lib, "advapi32")
41 int get_modified_time(
const std::string& path) {
43 HANDLE hFile = CreateFile(path.c_str(), 0, 0,
44 NULL, OPEN_EXISTING, 0, NULL);
45 if (hFile == INVALID_HANDLE_VALUE) {
46 throw CanteraError(
"get_modified_time",
"Couldn't open file:" + path);
49 GetFileTime(hFile, NULL, NULL, &modified);
51 return static_cast<int>(modified.dwLowDateTime);
54 stat(path.c_str(), &attrib);
55 return static_cast<int>(attrib.st_mtime);
59 Application::Messages::Messages()
68 if (msg.size() != 0) {
69 errorMessage.push_back(
70 "\n\n************************************************\n"
72 "************************************************\n\n"
74 "\nError: " + msg +
"\n");
76 errorMessage.push_back(r);
82 return static_cast<int>(errorMessage.size());
87 logwriter.reset(_logwriter);
92 logwriter->write(msg);
97 logwriter->writeendl();
105 std::unique_lock<std::mutex> msgLock(
msg_mutex);
106 std::thread::id curId = std::this_thread::get_id();
107 auto iter = m_threadMsgMap.find(curId);
108 if (iter != m_threadMsgMap.end()) {
109 return iter->second.get();
112 m_threadMsgMap.insert({curId, pMsgs});
118 std::unique_lock<std::mutex> msgLock(
msg_mutex);
119 std::thread::id curId = std::this_thread::get_id();
120 auto iter = m_threadMsgMap.find(curId);
121 if (iter != m_threadMsgMap.end()) {
122 m_threadMsgMap.erase(iter);
127 m_suppress_deprecation_warnings(false),
128 m_fatal_deprecation_warnings(false),
129 m_suppress_thermo_warnings(false)
139 std::unique_lock<std::mutex> appLock(
app_mutex);
149 f.second.first->unlock();
150 delete f.second.first;
157 std::unique_lock<std::mutex> appLock(
app_mutex);
165 const std::string& extra)
167 if (m_fatal_deprecation_warnings) {
169 }
else if (m_suppress_deprecation_warnings ||
warnings.count(method)) {
173 writelog(fmt::format(
"DeprecationWarning: {}: {}", method, extra));
178 const std::string& extra)
180 writelog(fmt::format(
"CanteraWarning: {}: {}", method, extra));
191 std::unique_lock<std::mutex> xmlLock(
xml_mutex);
193 int mtime = get_modified_time(path);
198 std::pair<XML_Node*, int> cache =
xmlfiles[path];
199 if (cache.second == mtime) {
206 string::size_type idot = path.rfind(
'.');
209 ext = path.substr(idot, path.size());
214 if (ext !=
".xml" && ext !=
".ctml") {
217 x->
build(phase_xml, path);
228 std::unique_lock<std::mutex> xmlLock(
xml_mutex);
229 std::pair<XML_Node*, int>& entry =
xmlfiles[text];
235 size_t start = text.find_first_not_of(
" \t\r\n");
236 if (text.substr(start,1) ==
"<") {
242 entry.first->build(s,
"[string]");
248 std::unique_lock<std::mutex> xmlLock(
xml_mutex);
251 f.second.first->unlock();
252 delete f.second.first;
263 long int Application::readStringRegistryKey(
const std::string& keyName,
const std::string& valueName,
264 std::string& value,
const std::string& defaultValue)
267 long open_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_READ, &key);
268 if (open_error != ERROR_SUCCESS) {
271 value = defaultValue;
273 DWORD bufferSize =
sizeof(buffer);
275 error = RegQueryValueEx(key, valueName.c_str(), 0, NULL, (LPBYTE) buffer, &bufferSize);
276 if (ERROR_SUCCESS == error) {
293 if (!errorMessage.empty()) {
294 return errorMessage.back();
296 return "<no Cantera error>";
302 for (
size_t j = 0; j < errorMessage.size(); j++) {
303 f << errorMessage[j] << endl;
305 errorMessage.clear();
310 for (
size_t j = 0; j < errorMessage.size(); j++) {
314 errorMessage.clear();
327 std::string pathsep =
";";
329 std::string pathsep =
":";
332 if (getenv(
"CANTERA_DATA") != 0) {
333 string s = string(getenv(
"CANTERA_DATA"));
335 size_t end = s.find(pathsep);
337 inputDirs.push_back(s.substr(start, end-start));
339 end = s.find(pathsep, start);
341 inputDirs.push_back(s.substr(start,end));
348 std::string installDir;
349 readStringRegistryKey(
"SOFTWARE\\Cantera\\Cantera " CANTERA_SHORT_VERSION,
350 "InstallDir", installDir,
"");
351 if (installDir !=
"") {
352 inputDirs.push_back(installDir +
"data");
356 const char* old_pythonpath = getenv(
"PYTHONPATH");
357 std::string pythonpath =
"PYTHONPATH=" + installDir +
"\\bin";
358 if (old_pythonpath) {
360 pythonpath.append(old_pythonpath);
362 _putenv(pythonpath.c_str());
369 inputDirs.push_back(
"/Applications/Cantera/data");
376 string datadir = string(CANTERA_DATA);
383 std::unique_lock<std::mutex> dirLock(
dir_mutex);
390 if (d.find(
"~/") == 0 || d.find(
"~\\") == 0) {
391 char* home = getenv(
"HOME");
393 home = getenv(
"USERPROFILE");
396 d = home + d.substr(1,
npos);
412 std::unique_lock<std::mutex> dirLock(
dir_mutex);
413 string::size_type islash = name.find(
'/');
414 string::size_type ibslash = name.find(
'\\');
415 string::size_type icolon = name.find(
':');
419 if (name.find(
"~/") == 0 || name.find(
"~\\") == 0) {
420 char* home = getenv(
"HOME");
422 home = getenv(
"USERPROFILE");
425 string full_name = home + name.substr(1,
npos);
426 std::ifstream fin(full_name);
431 "Input file '{}' not found", name);
437 if (islash == 0 || ibslash == 0
438 || (icolon == 1 && (ibslash == 2 || islash == 2)))
440 std::ifstream fin(name);
445 "Input file '{}' not found", name);
451 size_t nd = dirs.size();
452 for (
size_t i = 0; i < nd; i++) {
453 string full_name = dirs[i] +
"/" + name;
454 std::ifstream fin(full_name);
459 string msg =
"\nInput file " + name +
" not found in director";
460 msg += (nd == 1 ?
"y " :
"ies ");
461 for (
size_t i = 0; i < nd; i++) {
462 msg +=
"\n'" + dirs[i] +
"'";
468 msg +=
"To fix this problem, either:\n";
469 msg +=
" a) move the missing files into the local directory;\n";
470 msg +=
" b) define environment variable CANTERA_DATA to\n";
471 msg +=
" point to the directory containing the file.";
Class to carry out messages.
std::vector< std::string > errorMessage
Current list of error messages.
std::unique_ptr< Logger > logwriter
Current pointer to the logwriter.
void writelogendl()
Write an end of line character to the screen and flush output.
Messages * operator->()
Provide a pointer dereferencing overloaded operator.
void removeThreadMessages()
Remove a local thread message.
Class to hold global data.
std::set< std::string > warnings
Vector of deprecation warnings that have been emitted (to suppress duplicates)
XML_Node * get_XML_File(const std::string &file, int debug=0)
Return a pointer to the XML tree for a Cantera input file.
static Application * s_app
Pointer to the single Application instance.
void writelog(const std::string &msg)
Write a message to the screen.
std::vector< std::string > inputDirs
Current vector of input directories to search for input files.
static Application * Instance()
Return a pointer to the one and only instance of class Application.
virtual ~Application()
Destructor for class deletes global data.
XML_Node * get_XML_from_string(const std::string &text)
Read a CTI or CTML string and fill up an XML tree.
void close_XML_File(const std::string &file)
Close an XML File.
void thread_complete()
Delete and free memory allocated per thread in multithreaded applications.
std::map< std::string, std::pair< XML_Node *, int > > xmlfiles
Current vector of XML file trees that have been previously parsed The second element of the value is ...
shared_ptr< Messages > pMessages_t
Typedef for thread specific messages.
void warn_deprecated(const std::string &method, const std::string &extra="")
Print a warning indicating that method is deprecated.
void warn_user(const std::string &method, const std::string &extra="")
Print a user warning arising during usage of method.
Application()
Constructor for class sets up the initial conditions Protected ctor access thru static member functio...
void writelogendl()
Write an endl to the screen and flush output.
static void ApplicationDestroy()
Static function that destroys the application class's data.
Base class for exceptions thrown by Cantera classes.
Base class for 'loggers' that write text messages to log files.
static Unit * units()
Initialize the static Unit class.
Class XML_Node is a tree-based representation of the contents of an XML file.
void build(const std::string &filename)
Populate the XML tree from an input file.
void lock()
Set the lock for this node and all of its children.
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
void addError(const std::string &r, const std::string &msg="")
Set an error condition in the application class without throwing an exception.
void logErrors()
Prints all of the error messages using writelog.
std::string lastErrorMessage()
Retrieve the last error message in a string.
void getErrors(std::ostream &f)
Prints all of the error messages to an ostream.
int getErrorCount()
Return the number of errors that have been encountered so far.
void popError()
Discard the last error message.
const size_t npos
index returned by functions to indicate "no position"
void writelog(const std::string &msg)
Write a message to the screen.
void setLogger(Logger *logwriter)
Install a logger.
Namespace for the Cantera kernel.
static std::mutex app_mutex
Mutex for creating singletons within the application object.
static std::mutex xml_mutex
Mutex for controlling access to XML file storage.
static std::mutex dir_mutex
Mutex for input directory access.
std::string stripnonprint(const std::string &s)
Strip non-printing characters wherever they are.
static std::mutex msg_mutex
Mutex for access to string messages.
Contains declarations for string manipulation functions within Cantera.
Header for units conversion utilities, which are used to translate user input from input files (See I...