26#pragma comment(lib, "advapi32")
41int 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);
59Application::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();
102 logwriter->warn(warning, msg);
110 std::unique_lock<std::mutex> msgLock(
msg_mutex);
111 std::thread::id curId = std::this_thread::get_id();
112 auto iter = m_threadMsgMap.find(curId);
113 if (iter != m_threadMsgMap.end()) {
114 return iter->second.get();
117 m_threadMsgMap.insert({curId, pMsgs});
123 std::unique_lock<std::mutex> msgLock(
msg_mutex);
124 std::thread::id curId = std::this_thread::get_id();
125 auto iter = m_threadMsgMap.find(curId);
126 if (iter != m_threadMsgMap.end()) {
127 m_threadMsgMap.erase(iter);
132 m_suppress_deprecation_warnings(false),
133 m_fatal_deprecation_warnings(false),
134 m_suppress_thermo_warnings(false),
135 m_suppress_warnings(false),
136 m_fatal_warnings(false),
137#if CT_LEGACY_RATE_CONSTANTS
138 m_use_legacy_rate_constants(true)
140 m_use_legacy_rate_constants(false)
151 std::unique_lock<std::mutex> appLock(
app_mutex);
161 f.second.first->unlock();
162 delete f.second.first;
169 std::unique_lock<std::mutex> appLock(
app_mutex);
177 const std::string& extra)
179 if (m_fatal_deprecation_warnings) {
181 }
else if (m_suppress_deprecation_warnings ||
warnings.count(method)) {
185 warnlog(
"Deprecation", fmt::format(
"{}: {}", method, extra));
189 const std::string& method,
190 const std::string& extra)
192 if (m_fatal_warnings) {
194 }
else if (m_suppress_warnings) {
197 warnlog(warning, fmt::format(
"{}: {}", method, extra));
207 std::unique_lock<std::mutex> xmlLock(
xml_mutex);
209 int mtime = get_modified_time(path);
214 std::pair<XML_Node*, int> cache =
xmlfiles[path];
215 if (cache.second == mtime) {
222 string::size_type idot = path.rfind(
'.');
225 ext = path.substr(idot, path.size());
230 if (ext !=
".xml" && ext !=
".ctml") {
233 x->
build(phase_xml, path);
244 std::unique_lock<std::mutex> xmlLock(
xml_mutex);
245 std::pair<XML_Node*, int>& entry =
xmlfiles[text];
251 size_t start = text.find_first_not_of(
" \t\r\n");
252 if (text.substr(start,1) ==
"<") {
258 entry.first->build(s,
"[string]");
264 std::unique_lock<std::mutex> xmlLock(
xml_mutex);
267 f.second.first->unlock();
268 delete f.second.first;
279long int Application::readStringRegistryKey(
const std::string& keyName,
const std::string& valueName,
280 std::string& value,
const std::string& defaultValue)
283 long open_error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_READ, &key);
284 if (open_error != ERROR_SUCCESS) {
287 value = defaultValue;
289 DWORD bufferSize =
sizeof(buffer);
291 error = RegQueryValueEx(key, valueName.c_str(), 0, NULL, (LPBYTE) buffer, &bufferSize);
292 if (ERROR_SUCCESS == error) {
309 if (!errorMessage.empty()) {
310 return errorMessage.back();
312 return "<no Cantera error>";
318 for (
size_t j = 0; j < errorMessage.size(); j++) {
319 f << errorMessage[j] << endl;
321 errorMessage.clear();
326 for (
size_t j = 0; j < errorMessage.size(); j++) {
330 errorMessage.clear();
343 std::string pathsep =
";";
345 std::string pathsep =
":";
348 if (getenv(
"CANTERA_DATA") != 0) {
349 string s = string(getenv(
"CANTERA_DATA"));
351 size_t end = s.find(pathsep);
353 inputDirs.push_back(s.substr(start, end-start));
355 end = s.find(pathsep, start);
357 inputDirs.push_back(s.substr(start,end));
364 std::string installDir;
365 readStringRegistryKey(
"SOFTWARE\\Cantera\\Cantera " CANTERA_SHORT_VERSION,
366 "InstallDir", installDir,
"");
367 if (installDir !=
"") {
368 inputDirs.push_back(installDir +
"data");
372 const char* old_pythonpath = getenv(
"PYTHONPATH");
373 std::string pythonpath =
"PYTHONPATH=" + installDir +
"\\bin";
374 if (old_pythonpath) {
376 pythonpath.append(old_pythonpath);
378 _putenv(pythonpath.c_str());
385 inputDirs.push_back(
"/Applications/Cantera/data");
392 string datadir = string(CANTERA_DATA);
399 std::unique_lock<std::mutex> dirLock(
dir_mutex);
406 if (d.find(
"~/") == 0 || d.find(
"~\\") == 0) {
407 char* home = getenv(
"HOME");
409 home = getenv(
"USERPROFILE");
412 d = home + d.substr(1,
npos);
428 std::unique_lock<std::mutex> dirLock(
dir_mutex);
429 string::size_type islash = name.find(
'/');
430 string::size_type ibslash = name.find(
'\\');
431 string::size_type icolon = name.find(
':');
435 if (name.find(
"~/") == 0 || name.find(
"~\\") == 0) {
436 char* home = getenv(
"HOME");
438 home = getenv(
"USERPROFILE");
441 string full_name = home + name.substr(1,
npos);
442 std::ifstream fin(full_name);
447 "Input file '{}' not found", name);
453 if (islash == 0 || ibslash == 0
454 || (icolon == 1 && (ibslash == 2 || islash == 2)))
456 std::ifstream fin(name);
461 "Input file '{}' not found", name);
467 size_t nd = dirs.size();
468 for (
size_t i = 0; i < nd; i++) {
469 string full_name = dirs[i] +
"/" + name;
470 std::ifstream fin(full_name);
475 string msg =
"\nInput file " + name +
" not found in director";
476 msg += (nd == 1 ?
"y " :
"ies ");
477 for (
size_t i = 0; i < nd; i++) {
478 msg +=
"\n'" + dirs[i] +
"'";
484 msg +=
"To fix this problem, either:\n";
485 msg +=
" a) move the missing files into the local directory;\n";
486 msg +=
" b) define environment variable CANTERA_DATA to\n";
487 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.
void warn(const std::string &warning, const std::string &method, const std::string &extra="")
Generate a general purpose warning; repeated warnings are not suppressed.
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.
void warnlog(const std::string &warning, const std::string &msg)
Write a warning message to the screen.
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.
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.
void writelog(const std::string &msg)
Write a message to the screen.
void setLogger(Logger *logwriter)
Install a logger.
void warnlog(const std::string &warning, const std::string &msg)
Write a warning message to the screen.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
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...