LCOV - code coverage report
Current view: top level - src/utils - MooseUtils.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 502 605 83.0 %
Date: 2025-08-08 20:01:16 Functions: 70 78 89.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : // MOOSE includes
      11             : #include "MooseUtils.h"
      12             : #include "MooseError.h"
      13             : #include "MaterialProperty.h"
      14             : #include "MultiMooseEnum.h"
      15             : #include "InputParameters.h"
      16             : #include "ExecFlagEnum.h"
      17             : #include "InfixIterator.h"
      18             : #include "Registry.h"
      19             : #include "MortarConstraintBase.h"
      20             : #include "MortarNodalAuxKernel.h"
      21             : #include "ExecFlagRegistry.h"
      22             : #include "RestartableDataReader.h"
      23             : 
      24             : #include "libmesh/utility.h"
      25             : #include "libmesh/elem.h"
      26             : 
      27             : // External includes
      28             : #include "pcrecpp.h"
      29             : #include "tinydir.h"
      30             : 
      31             : // C++ includes
      32             : #include <iostream>
      33             : #include <fstream>
      34             : #include <istream>
      35             : #include <iterator>
      36             : #include <filesystem>
      37             : #include <ctime>
      38             : #include <cstdlib>
      39             : #include <regex>
      40             : 
      41             : // System includes
      42             : #include <sys/stat.h>
      43             : #include <numeric>
      44             : #include <unistd.h>
      45             : 
      46             : #include "petscsys.h"
      47             : 
      48             : #ifdef __WIN32__
      49             : #include <windows.h>
      50             : #include <winbase.h>
      51             : #include <fileapi.h>
      52             : #else
      53             : #include <sys/ioctl.h>
      54             : #endif
      55             : 
      56             : namespace MooseUtils
      57             : {
      58             : std::filesystem::path
      59      140458 : pathjoin(const std::filesystem::path & p)
      60             : {
      61      140458 :   return p;
      62             : }
      63             : 
      64             : std::string
      65           7 : runTestsExecutable()
      66             : {
      67           7 :   auto build_loc = pathjoin(Moose::getExecutablePath(), "run_tests");
      68           7 :   if (pathExists(build_loc) && checkFileReadable(build_loc))
      69           7 :     return build_loc;
      70             :   // TODO: maybe no path prefix - just moose_test_runner here?
      71           0 :   return pathjoin(Moose::getExecutablePath(), "moose_test_runner");
      72           7 : }
      73             : 
      74             : std::string
      75           7 : findTestRoot()
      76             : {
      77           7 :   std::string path = ".";
      78           7 :   for (int i = 0; i < 5; i++)
      79             :   {
      80           7 :     auto testroot = pathjoin(path, "testroot");
      81           7 :     if (pathExists(testroot) && checkFileReadable(testroot))
      82           7 :       return testroot;
      83           0 :     path += "/..";
      84           7 :   }
      85           0 :   return "";
      86           7 : }
      87             : 
      88             : bool
      89        2648 : parsesToReal(const std::string & input)
      90             : {
      91        2648 :   std::istringstream ss(input);
      92             :   Real real_value;
      93        2648 :   if (ss >> real_value && ss.eof())
      94        1941 :     return true;
      95         707 :   return false;
      96        2648 : }
      97             : 
      98             : std::string
      99          14 : installedInputsDir(const std::string & app_name,
     100             :                    const std::string & dir_name,
     101             :                    const std::string & extra_error_msg)
     102             : {
     103             :   // See moose.mk for a detailed explanation of the assumed installed application
     104             :   // layout. Installed inputs are expected to be installed in "share/<app_name>/<folder>".
     105             :   // The binary, which has a defined location will be in "bin", a peer directory to "share".
     106             :   std::string installed_path =
     107          14 :       pathjoin(Moose::getExecutablePath(), "..", "share", app_name, dir_name);
     108             : 
     109          14 :   auto test_root = pathjoin(installed_path, "testroot");
     110          14 :   if (!pathExists(installed_path))
     111           0 :     mooseError("Couldn't locate any installed inputs to copy in path: ",
     112             :                installed_path,
     113           0 :                '\n',
     114             :                extra_error_msg);
     115             : 
     116          14 :   checkFileReadable(test_root);
     117          28 :   return installed_path;
     118          14 : }
     119             : 
     120             : std::string
     121           0 : docsDir(const std::string & app_name)
     122             : {
     123             :   // See moose.mk for a detailed explanation of the assumed installed application
     124             :   // layout. Installed docs are expected to be installed in "share/<app_name>/doc".
     125             :   // The binary, which has a defined location will be in "bin", a peer directory to "share".
     126           0 :   std::string installed_path = pathjoin(Moose::getExecutablePath(), "..", "share", app_name, "doc");
     127             : 
     128           0 :   auto docfile = pathjoin(installed_path, "css", "moose.css");
     129           0 :   if (pathExists(docfile) && checkFileReadable(docfile))
     130           0 :     return installed_path;
     131           0 :   return "";
     132           0 : }
     133             : 
     134             : std::string
     135    20487587 : mooseDocsURL(const std::string & path)
     136             : {
     137    20487587 :   return "https://mooseframework.inl.gov/" + path;
     138             : }
     139             : 
     140             : std::string
     141      236395 : replaceAll(std::string str, const std::string & from, const std::string & to)
     142             : {
     143      236395 :   size_t start_pos = 0;
     144      237146 :   while ((start_pos = str.find(from, start_pos)) != std::string::npos)
     145             :   {
     146         751 :     str.replace(start_pos, from.length(), to);
     147         751 :     start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
     148             :   }
     149      236395 :   return str;
     150             : }
     151             : 
     152             : std::string
     153        3412 : convertLatestCheckpoint(std::string orig)
     154             : {
     155        3412 :   auto slash_pos = orig.find_last_of("/");
     156        3412 :   auto path = orig.substr(0, slash_pos);
     157        3412 :   auto file = orig.substr(slash_pos + 1);
     158        3412 :   if (file != "LATEST")
     159        3100 :     return orig;
     160             : 
     161         312 :   auto converted = MooseUtils::getLatestCheckpointFilePrefix(MooseUtils::listDir(path));
     162             : 
     163         312 :   if (converted.empty())
     164           0 :     mooseError("Unable to find suitable recovery file!");
     165             : 
     166         312 :   return converted;
     167        3412 : }
     168             : 
     169             : // this implementation is copied from
     170             : // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C.2B.2B
     171             : int
     172        3665 : levenshteinDist(const std::string & s1, const std::string & s2)
     173             : {
     174             :   // To change the type this function manipulates and returns, change
     175             :   // the return type and the types of the two variables below.
     176        3665 :   auto s1len = s1.size();
     177        3665 :   auto s2len = s2.size();
     178             : 
     179        3665 :   auto column_start = (decltype(s1len))1;
     180             : 
     181        3665 :   auto column = new decltype(s1len)[s1len + 1];
     182        3665 :   std::iota(column + column_start, column + s1len + 1, column_start);
     183             : 
     184       36145 :   for (auto x = column_start; x <= s2len; x++)
     185             :   {
     186       32480 :     column[0] = x;
     187       32480 :     auto last_diagonal = x - column_start;
     188      413569 :     for (auto y = column_start; y <= s1len; y++)
     189             :     {
     190      381089 :       auto old_diagonal = column[y];
     191      381089 :       auto possibilities = {
     192      381089 :           column[y] + 1, column[y - 1] + 1, last_diagonal + (s1[y - 1] == s2[x - 1] ? 0 : 1)};
     193      381089 :       column[y] = std::min(possibilities);
     194      381089 :       last_diagonal = old_diagonal;
     195             :     }
     196             :   }
     197        3665 :   auto result = column[s1len];
     198        3665 :   delete[] column;
     199        3665 :   return result;
     200             : }
     201             : 
     202             : void
     203     7131568 : escape(std::string & str)
     204             : {
     205     7131568 :   std::map<char, std::string> escapes;
     206     7131568 :   escapes['\a'] = "\\a";
     207     7131568 :   escapes['\b'] = "\\b";
     208     7131568 :   escapes['\f'] = "\\f";
     209     7131568 :   escapes['\n'] = "\\n";
     210     7131568 :   escapes['\t'] = "\\t";
     211     7131568 :   escapes['\v'] = "\\v";
     212     7131568 :   escapes['\r'] = "\\r";
     213             : 
     214    57052544 :   for (const auto & it : escapes)
     215    49921132 :     for (size_t pos = 0; (pos = str.find(it.first, pos)) != std::string::npos;
     216         156 :          pos += it.second.size())
     217         156 :       str.replace(pos, 1, it.second);
     218     7131568 : }
     219             : 
     220             : std::string
     221      477378 : removeExtraWhitespace(const std::string & input)
     222             : {
     223      954756 :   return std::regex_replace(input, std::regex("^\\s+|\\s+$|\\s+(?=\\s)"), "");
     224             : }
     225             : 
     226             : bool
     227           0 : pathContains(const std::string & expression,
     228             :              const std::string & string_to_find,
     229             :              const std::string & delims)
     230             : {
     231           0 :   std::vector<std::string> elements;
     232           0 :   tokenize(expression, elements, 0, delims);
     233             : 
     234             :   std::vector<std::string>::iterator found_it =
     235           0 :       std::find(elements.begin(), elements.end(), string_to_find);
     236           0 :   if (found_it != elements.end())
     237           0 :     return true;
     238             :   else
     239           0 :     return false;
     240           0 : }
     241             : 
     242             : bool
     243       24058 : pathExists(const std::string & path)
     244             : {
     245             :   struct stat buffer;
     246       24058 :   return (stat(path.c_str(), &buffer) == 0);
     247             : }
     248             : 
     249             : bool
     250      358161 : checkFileReadable(const std::string & filename,
     251             :                   bool check_line_endings,
     252             :                   bool throw_on_unreadable,
     253             :                   bool check_for_git_lfs_pointer)
     254             : {
     255      358161 :   std::ifstream in(filename.c_str(), std::ifstream::in);
     256      358161 :   if (in.fail())
     257             :   {
     258       72602 :     if (throw_on_unreadable)
     259          17 :       mooseError(
     260          23 :           (std::string("Unable to open file \"") + filename +
     261          20 :            std::string("\". Check to make sure that it exists and that you have read permission."))
     262          18 :               .c_str());
     263             :     else
     264       72585 :       return false;
     265             :   }
     266             : 
     267      285559 :   if (check_line_endings)
     268             :   {
     269       67309 :     std::istream_iterator<char> iter(in);
     270       67309 :     std::istream_iterator<char> eos;
     271       67309 :     in >> std::noskipws;
     272    82408194 :     while (iter != eos)
     273    82340885 :       if (*iter++ == '\r')
     274           0 :         mooseError(filename + " contains Windows(DOS) line endings which are not supported.");
     275             :   }
     276             : 
     277      285559 :   if (check_for_git_lfs_pointer && checkForGitLFSPointer(in))
     278           8 :     mooseError(filename + " appears to be a Git-LFS pointer. Make sure you have \"git-lfs\" "
     279             :                           "installed so that you may pull this file.");
     280      285551 :   in.close();
     281             : 
     282      285551 :   return true;
     283      358137 : }
     284             : 
     285             : bool
     286      217692 : checkForGitLFSPointer(std::ifstream & file)
     287             : {
     288             :   mooseAssert(file.is_open(), "Passed in file handle is not open");
     289             : 
     290      217692 :   std::string line;
     291             : 
     292             :   // git-lfs pointer files contain several name value pairs. The specification states that the
     293             :   // first name/value pair must be "version {url}". We'll do a simplified check for that.
     294      217692 :   file.seekg(0);
     295      217692 :   std::getline(file, line);
     296      217692 :   if (line.find("version https://") != std::string::npos)
     297           8 :     return true;
     298             :   else
     299      217684 :     return false;
     300      217692 : }
     301             : 
     302             : bool
     303         270 : checkFileWriteable(const std::string & filename, bool throw_on_unwritable)
     304             : {
     305         270 :   std::ofstream out(filename.c_str(), std::ios_base::app);
     306         270 :   if (out.fail())
     307             :   {
     308           0 :     if (throw_on_unwritable)
     309           0 :       mooseError(
     310           0 :           (std::string("Unable to open file \"") + filename +
     311           0 :            std::string("\". Check to make sure that it exists and that you have write permission."))
     312           0 :               .c_str());
     313             :     else
     314           0 :       return false;
     315             :   }
     316             : 
     317         270 :   out.close();
     318             : 
     319         270 :   return true;
     320         270 : }
     321             : 
     322             : void
     323      261093 : parallelBarrierNotify(const Parallel::Communicator & comm, bool messaging)
     324             : {
     325             :   processor_id_type secondary_processor_id;
     326             : 
     327      261093 :   if (messaging)
     328           0 :     Moose::out << "Waiting For Other Processors To Finish" << std::endl;
     329      261093 :   if (comm.rank() == 0)
     330             :   {
     331             :     // The primary process is already through, so report it
     332      195004 :     if (messaging)
     333           0 :       Moose::out << "Jobs complete: 1/" << comm.size() << (1 == comm.size() ? "\n" : "\r")
     334           0 :                  << std::flush;
     335      261093 :     for (unsigned int i = 2; i <= comm.size(); ++i)
     336             :     {
     337       66089 :       comm.receive(MPI_ANY_SOURCE, secondary_processor_id);
     338       66089 :       if (messaging)
     339           0 :         Moose::out << "Jobs complete: " << i << "/" << comm.size()
     340           0 :                    << (i == comm.size() ? "\n" : "\r") << std::flush;
     341             :     }
     342             :   }
     343             :   else
     344             :   {
     345       66089 :     secondary_processor_id = comm.rank();
     346       66089 :     comm.send(0, secondary_processor_id);
     347             :   }
     348             : 
     349      261093 :   comm.barrier();
     350      261093 : }
     351             : 
     352             : void
     353          10 : serialBegin(const libMesh::Parallel::Communicator & comm, bool warn)
     354             : {
     355             :   // unless we are the first processor...
     356          10 :   if (comm.rank() > 0)
     357             :   {
     358             :     // ...wait for the previous processor to finish
     359           3 :     int dummy = 0;
     360           3 :     comm.receive(comm.rank() - 1, dummy);
     361             :   }
     362           7 :   else if (warn)
     363           0 :     mooseWarning("Entering serial execution block (use only for debugging)");
     364          10 : }
     365             : 
     366             : void
     367          10 : serialEnd(const libMesh::Parallel::Communicator & comm, bool warn)
     368             : {
     369             :   // unless we are the last processor...
     370          10 :   if (comm.rank() + 1 < comm.size())
     371             :   {
     372             :     // ...notify the next processor of its turn
     373           3 :     int dummy = 0;
     374           3 :     comm.send(comm.rank() + 1, dummy);
     375             :   }
     376             : 
     377          10 :   comm.barrier();
     378          10 :   if (comm.rank() == 0 && warn)
     379           0 :     mooseWarning("Leaving serial execution block (use only for debugging)");
     380          10 : }
     381             : 
     382             : bool
     383       24561 : hasExtension(const std::string & filename, std::string ext, bool strip_exodus_ext)
     384             : {
     385             :   // Extract the extension, w/o the '.'
     386       24561 :   std::string file_ext;
     387       24561 :   if (strip_exodus_ext)
     388             :   {
     389             :     pcrecpp::RE re(
     390         616 :         ".*\\.([^\\.]*?)(?:-s\\d+)?\\s*$"); // capture the complete extension, ignoring -s*
     391         616 :     re.FullMatch(filename, &file_ext);
     392         616 :   }
     393             :   else
     394             :   {
     395       23945 :     pcrecpp::RE re(".*\\.([^\\.]*?)\\s*$"); // capture the complete extension
     396       23945 :     re.FullMatch(filename, &file_ext);
     397       23945 :   }
     398             : 
     399             :   // Perform the comparision
     400       24561 :   if (file_ext == ext)
     401       13334 :     return true;
     402             :   else
     403       11227 :     return false;
     404       24561 : }
     405             : 
     406             : std::string
     407         688 : getExtension(const std::string & filename, const bool rfind)
     408             : {
     409         688 :   std::string file_ext = "";
     410         688 :   if (filename != "")
     411             :   {
     412             :     // The next line splits filename at the last "/" and gives the file name after "/"
     413         674 :     const std::string stripped_filename = splitFileName<std::string>(filename).second;
     414         674 :     auto pos = rfind ? stripped_filename.rfind(".") : stripped_filename.find(".");
     415         674 :     if (pos != std::string::npos)
     416         208 :       file_ext += stripped_filename.substr(pos + 1, std::string::npos);
     417         674 :   }
     418             : 
     419         688 :   return file_ext;
     420           0 : }
     421             : 
     422             : std::string
     423         276 : stripExtension(const std::string & s, const bool rfind)
     424             : {
     425         276 :   const std::string ext = getExtension(s, rfind);
     426         276 :   const bool offset = (ext.size() != 0);
     427             :   // -1 offset accounts for the extension's leading dot ("."), if there is an extension
     428         552 :   return s.substr(0, s.size() - ext.size() - offset);
     429         276 : }
     430             : 
     431             : std::string
     432           7 : getCurrentWorkingDir()
     433             : {
     434             :   // Note: At the time of creating this method, our minimum compiler still
     435             :   // does not support <filesystem>. Additionally, the inclusion of that header
     436             :   // requires an additional library to be linked so for now, we'll just
     437             :   // use the Unix standard library to get us the cwd().
     438           7 :   constexpr unsigned int BUF_SIZE = 1024;
     439             :   char buffer[BUF_SIZE];
     440             : 
     441           7 :   return getcwd(buffer, BUF_SIZE) != nullptr ? buffer : "";
     442             : }
     443             : 
     444             : void
     445           8 : makedirs(const std::string & dir_name, bool throw_on_failure)
     446             : {
     447             :   // split path into directories with delimiter '/'
     448           8 :   std::vector<std::string> split_dir_names;
     449           8 :   MooseUtils::tokenize(dir_name, split_dir_names);
     450             : 
     451           8 :   auto n = split_dir_names.size();
     452             : 
     453             :   // remove '.' and '..' when possible
     454           8 :   auto i = n;
     455           8 :   i = 0;
     456          36 :   while (i != n)
     457             :   {
     458          28 :     if (split_dir_names[i] == ".")
     459             :     {
     460           3 :       for (auto j = i + 1; j < n; ++j)
     461           2 :         split_dir_names[j - 1] = split_dir_names[j];
     462           1 :       --n;
     463             :     }
     464          27 :     else if (i > 0 && split_dir_names[i] == ".." && split_dir_names[i - 1] != "..")
     465             :     {
     466           4 :       for (auto j = i + 1; j < n; ++j)
     467           3 :         split_dir_names[j - 2] = split_dir_names[j];
     468           1 :       n -= 2;
     469           1 :       --i;
     470             :     }
     471             :     else
     472          26 :       ++i;
     473             :   }
     474           8 :   if (n == 0)
     475           0 :     return;
     476             : 
     477           8 :   split_dir_names.resize(n);
     478             : 
     479             :   // start creating directories recursively
     480           8 :   std::string cur_dir = dir_name[0] == '/' ? "" : ".";
     481          32 :   for (auto & dir : split_dir_names)
     482             :   {
     483          25 :     cur_dir += "/" + dir;
     484             : 
     485          25 :     if (!pathExists(cur_dir))
     486             :     {
     487          17 :       auto code = Utility::mkdir(cur_dir.c_str());
     488          17 :       if (code != 0)
     489             :       {
     490           1 :         std::string msg = "Failed creating directory " + dir_name;
     491           1 :         if (throw_on_failure)
     492           1 :           throw std::invalid_argument(msg);
     493             :         else
     494           0 :           mooseError(msg);
     495           1 :       }
     496             :     }
     497             :   }
     498           9 : }
     499             : 
     500             : void
     501           7 : removedirs(const std::string & dir_name, bool throw_on_failure)
     502             : {
     503             :   // split path into directories with delimiter '/'
     504           7 :   std::vector<std::string> split_dir_names;
     505           7 :   MooseUtils::tokenize(dir_name, split_dir_names);
     506             : 
     507           7 :   auto n = split_dir_names.size();
     508             : 
     509             :   // remove '.' and '..' when possible
     510           7 :   auto i = n;
     511           7 :   i = 0;
     512          34 :   while (i != n)
     513             :   {
     514          27 :     if (split_dir_names[i] == ".")
     515             :     {
     516           3 :       for (auto j = i + 1; j < n; ++j)
     517           2 :         split_dir_names[j - 1] = split_dir_names[j];
     518           1 :       --n;
     519             :     }
     520          26 :     else if (i > 0 && split_dir_names[i] == ".." && split_dir_names[i - 1] != "..")
     521             :     {
     522           4 :       for (auto j = i + 1; j < n; ++j)
     523           3 :         split_dir_names[j - 2] = split_dir_names[j];
     524           1 :       n -= 2;
     525           1 :       --i;
     526             :     }
     527             :     else
     528          25 :       ++i;
     529             :   }
     530           7 :   if (n == 0)
     531           0 :     return;
     532             : 
     533           7 :   split_dir_names.resize(n);
     534             : 
     535             :   // start removing directories recursively
     536           7 :   std::string base_dir = dir_name[0] == '/' ? "" : ".";
     537          23 :   for (i = n; i > 0; --i)
     538             :   {
     539          19 :     std::string cur_dir = base_dir;
     540          19 :     auto j = i;
     541          71 :     for (j = 0; j < i; ++j)
     542          52 :       cur_dir += "/" + split_dir_names[j];
     543             : 
     544             :     // listDir should return at least '.' and '..'
     545          19 :     if (pathExists(cur_dir) && listDir(cur_dir).size() == 2)
     546             :     {
     547          16 :       auto code = rmdir(cur_dir.c_str());
     548          16 :       if (code != 0)
     549             :       {
     550           0 :         std::string msg = "Failed removing directory " + dir_name;
     551           0 :         if (throw_on_failure)
     552           0 :           throw std::invalid_argument(msg);
     553             :         else
     554           0 :           mooseError(msg);
     555           0 :       }
     556             :     }
     557             :     else
     558             :       // stop removing
     559           3 :       break;
     560          19 :   }
     561           7 : }
     562             : 
     563             : std::string
     564          19 : camelCaseToUnderscore(const std::string & camel_case_name)
     565             : {
     566          19 :   std::string replaced = camel_case_name;
     567             :   // Put underscores in front of each contiguous set of capital letters
     568          19 :   pcrecpp::RE("(?!^)(?<![A-Z_])([A-Z]+)").GlobalReplace("_\\1", &replaced);
     569             : 
     570             :   // Convert all capital letters to lower case
     571          19 :   std::transform(replaced.begin(), replaced.end(), replaced.begin(), ::tolower);
     572          19 :   return replaced;
     573           0 : }
     574             : 
     575             : std::string
     576         542 : underscoreToCamelCase(const std::string & underscore_name, bool leading_upper_case)
     577             : {
     578         542 :   pcrecpp::StringPiece input(underscore_name);
     579         542 :   pcrecpp::RE re("([^_]*)(_|$)");
     580             : 
     581         542 :   std::string result;
     582         542 :   std::string us, not_us;
     583         542 :   bool make_upper = leading_upper_case;
     584         554 :   while (re.Consume(&input, &not_us, &us))
     585             :   {
     586         554 :     if (not_us.length() > 0)
     587             :     {
     588         548 :       if (make_upper)
     589             :       {
     590         546 :         result += std::toupper(not_us[0]);
     591         546 :         if (not_us.length() > 1)
     592         546 :           result += not_us.substr(1);
     593             :       }
     594             :       else
     595           2 :         result += not_us;
     596             :     }
     597         554 :     if (us == "")
     598         542 :       break;
     599             : 
     600             :     // Toggle flag so next match is upper cased
     601          12 :     make_upper = true;
     602             :   }
     603             : 
     604        1084 :   return result;
     605         542 : }
     606             : 
     607             : std::string
     608     4808757 : shortName(const std::string & name)
     609             : {
     610     4808757 :   return name.substr(name.find_last_of('/') != std::string::npos ? name.find_last_of('/') + 1 : 0);
     611             : }
     612             : 
     613             : std::string
     614     1498330 : baseName(const std::string & name)
     615             : {
     616     1498330 :   return name.substr(0, name.find_last_of('/') != std::string::npos ? name.find_last_of('/') : 0);
     617             : }
     618             : 
     619             : std::string
     620          11 : hostname()
     621             : {
     622             :   char hostname[1024];
     623          11 :   hostname[1023] = '\0';
     624             : #ifndef __WIN32__
     625          11 :   if (gethostname(hostname, 1023))
     626           0 :     mooseError("Failed to retrieve hostname!");
     627             : #else
     628             :   DWORD dwSize = sizeof(hostname);
     629             :   if (!GetComputerNameEx(ComputerNamePhysicalDnsHostname, hostname, &dwSize))
     630             :     mooseError("Failed to retrieve hostname!");
     631             : #endif
     632          11 :   return hostname;
     633             : }
     634             : 
     635             : unsigned short
     636      134100 : getTermWidth(bool use_environment)
     637             : {
     638             : #ifndef __WIN32__
     639             :   struct winsize w;
     640             : #else
     641             :   struct
     642             :   {
     643             :     unsigned short ws_col;
     644             :   } w;
     645             : #endif
     646             :   /**
     647             :    * Initialize the value we intend to populate just in case
     648             :    * the system call fails
     649             :    */
     650      134100 :   w.ws_col = std::numeric_limits<unsigned short>::max();
     651             : 
     652      134100 :   if (use_environment)
     653             :   {
     654      134100 :     char * pps_width = std::getenv("MOOSE_PPS_WIDTH");
     655      134100 :     if (pps_width != NULL)
     656             :     {
     657           0 :       std::stringstream ss(pps_width);
     658           0 :       ss >> w.ws_col;
     659           0 :     }
     660             :   }
     661             :   // Default to AUTO if no environment variable was set
     662      134100 :   if (w.ws_col == std::numeric_limits<unsigned short>::max())
     663             :   {
     664             : #ifndef __WIN32__
     665             :     try
     666             :     {
     667      134100 :       ioctl(0, TIOCGWINSZ, &w);
     668             :     }
     669             :     catch (...)
     670             : #endif
     671             :     {
     672             :     }
     673             :   }
     674             : 
     675             :   // Something bad happened, make sure we have a sane value
     676             :   // 132 seems good for medium sized screens, and is available as a GNOME preset
     677      134100 :   if (w.ws_col == std::numeric_limits<unsigned short>::max())
     678      134100 :     w.ws_col = 132;
     679             : 
     680      134100 :   return w.ws_col;
     681             : }
     682             : 
     683             : void
     684           0 : MaterialPropertyStorageDump(
     685             :     const HashMap<const libMesh::Elem *, HashMap<unsigned int, MaterialProperties>> & props)
     686             : {
     687             :   // Loop through the elements
     688           0 :   for (const auto & elem_it : props)
     689             :   {
     690           0 :     Moose::out << "Element " << elem_it.first->id() << '\n';
     691             : 
     692             :     // Loop through the sides
     693           0 :     for (const auto & side_it : elem_it.second)
     694             :     {
     695           0 :       Moose::out << "  Side " << side_it.first << '\n';
     696             : 
     697             :       // Loop over properties
     698           0 :       unsigned int cnt = 0;
     699           0 :       for (const auto & mat_prop : side_it.second)
     700             :       {
     701           0 :         if (auto mp = dynamic_cast<const MaterialProperty<Real> *>(&mat_prop))
     702             :         {
     703           0 :           Moose::out << "    Property " << cnt << '\n';
     704           0 :           cnt++;
     705             : 
     706             :           // Loop over quadrature points
     707           0 :           for (unsigned int qp = 0; qp < mp->size(); ++qp)
     708           0 :             Moose::out << "      prop[" << qp << "] = " << (*mp)[qp] << '\n';
     709             :         }
     710             :       }
     711             :     }
     712             :   }
     713             : 
     714           0 :   Moose::out << std::flush;
     715           0 : }
     716             : 
     717             : std::string &
     718       22537 : removeColor(std::string & msg)
     719             : {
     720       22537 :   pcrecpp::RE re("(\\33\\[3[0-7]m))", pcrecpp::DOTALL());
     721       22537 :   re.GlobalReplace(std::string(""), &msg);
     722       22537 :   return msg;
     723       22537 : }
     724             : 
     725             : void
     726           0 : addLineBreaks(std::string & message,
     727             :               unsigned int line_width /*= ConsoleUtils::console_line_length*/)
     728             : {
     729           0 :   for (auto i : make_range(int(message.length() / line_width)))
     730           0 :     message.insert((i + 1) * (line_width + 2) - 2, "\n");
     731           0 : }
     732             : 
     733             : void
     734     1371036 : indentMessage(const std::string & prefix,
     735             :               std::string & message,
     736             :               const char * color /*= COLOR_CYAN*/,
     737             :               bool indent_first_line,
     738             :               const std::string & post_prefix)
     739             : {
     740             :   // First we need to see if the message we need to indent (with color) also contains color codes
     741             :   // that span lines.
     742             :   // The code matches all of the XTERM constants (see XTermConstants.h). If it does, then we'll work
     743             :   // on formatting
     744             :   // each colored multiline chunk one at a time with the right codes.
     745     1371036 :   std::string colored_message;
     746     1371036 :   std::string curr_color = COLOR_DEFAULT; // tracks last color code before newline
     747     1371036 :   std::string line, color_code;
     748             : 
     749     1371036 :   bool ends_in_newline = message.empty() ? true : message.back() == '\n';
     750             : 
     751     1371036 :   bool first = true;
     752             : 
     753     1371036 :   std::istringstream iss(message);
     754     3473740 :   for (std::string line; std::getline(iss, line);) // loop over each line
     755             :   {
     756     2102704 :     const static pcrecpp::RE match_color(".*(\\33\\[3\\dm)((?!\\33\\[3\\d)[^\n])*");
     757     2102704 :     pcrecpp::StringPiece line_piece(line);
     758     2102704 :     match_color.FindAndConsume(&line_piece, &color_code);
     759             : 
     760     2102704 :     if (!first || indent_first_line)
     761     2102704 :       colored_message += color + prefix + post_prefix + curr_color;
     762             : 
     763     2102704 :     colored_message += line;
     764             : 
     765             :     // Only add a newline to the last line if it had one to begin with!
     766     2102704 :     if (!iss.eof() || ends_in_newline)
     767     2039294 :       colored_message += "\n";
     768             : 
     769     2102704 :     if (!color_code.empty())
     770      979398 :       curr_color = color_code; // remember last color of this line
     771             : 
     772     2102704 :     first = false;
     773     1371036 :   }
     774     1371036 :   message = colored_message;
     775     1371036 : }
     776             : 
     777             : std::list<std::string>
     778        3264 : listDir(const std::string path, bool files_only)
     779             : {
     780        3264 :   std::list<std::string> files;
     781             : 
     782        3264 :   tinydir_dir dir;
     783        3264 :   dir.has_next = 0; // Avoid a garbage value in has_next (clang StaticAnalysis)
     784        3264 :   tinydir_open(&dir, path.c_str());
     785             : 
     786       20602 :   while (dir.has_next)
     787             :   {
     788             :     tinydir_file file;
     789       17338 :     file.is_dir = 0; // Avoid a garbage value in is_dir (clang StaticAnalysis)
     790       17338 :     tinydir_readfile(&dir, &file);
     791             : 
     792       17338 :     if (!files_only || !file.is_dir)
     793       17338 :       files.push_back(path + "/" + file.name);
     794             : 
     795       17338 :     tinydir_next(&dir);
     796             :   }
     797             : 
     798        3264 :   tinydir_close(&dir);
     799             : 
     800        6528 :   return files;
     801           0 : }
     802             : 
     803             : std::list<std::string>
     804        2900 : getFilesInDirs(const std::list<std::string> & directory_list, const bool files_only /* = true */)
     805             : {
     806        2900 :   std::list<std::string> files;
     807             : 
     808        5834 :   for (const auto & dir_name : directory_list)
     809        2934 :     files.splice(files.end(), listDir(dir_name, files_only));
     810             : 
     811        2900 :   return files;
     812           0 : }
     813             : 
     814             : std::string
     815        3212 : getLatestCheckpointFilePrefix(const std::list<std::string> & checkpoint_files)
     816             : {
     817             :   // Create storage for newest restart files
     818             :   // Note that these might have the same modification time if the simulation was fast.
     819             :   // In that case we're going to save all of the "newest" files and sort it out momentarily
     820        3212 :   std::time_t newest_time = 0;
     821        3212 :   std::list<std::string> newest_restart_files;
     822             : 
     823             :   // Loop through all possible files and store the newest
     824       20456 :   for (const auto & cp_file : checkpoint_files)
     825             :   {
     826       17244 :     if (MooseUtils::hasExtension(cp_file, "rd"))
     827             :     {
     828             :       struct stat stats;
     829        6379 :       stat(cp_file.c_str(), &stats);
     830             : 
     831        6379 :       std::time_t mod_time = stats.st_mtime;
     832        6379 :       if (mod_time > newest_time)
     833             :       {
     834        3405 :         newest_restart_files.clear(); // If the modification time is greater, clear the list
     835        3405 :         newest_time = mod_time;
     836             :       }
     837             : 
     838        6379 :       if (mod_time == newest_time)
     839        5854 :         newest_restart_files.push_back(cp_file);
     840             :     }
     841             :   }
     842             : 
     843             :   // Loop through all of the newest files according the number in the file name
     844        3212 :   int max_file_num = -1;
     845        3212 :   std::string max_file;
     846        3212 :   std::string max_prefix;
     847             : 
     848             :   // Pull out the path including the number and the number itself
     849             :   // This takes something_blah_out_cp/0024-restart-1.rd
     850             :   // and returns "something_blah_out_cp/0024" as the "prefix"
     851             :   // and then "24" as the number itself
     852        3212 :   pcrecpp::RE re_file_num("(.*?(\\d+))-restart-\\d+.rd$");
     853             : 
     854             :   // Now, out of the newest files find the one with the largest number in it
     855        8852 :   for (const auto & res_file : newest_restart_files)
     856             :   {
     857        5640 :     int file_num = 0;
     858             : 
     859             :     // All of the file up to and including the digits
     860        5640 :     std::string file_prefix;
     861             : 
     862        5640 :     re_file_num.FullMatch(res_file, &file_prefix, &file_num);
     863             : 
     864        5640 :     if (file_num > max_file_num)
     865             :     {
     866             :       // Need both the header and the data
     867        3548 :       if (!RestartableDataReader::isAvailable(res_file))
     868           0 :         continue;
     869             : 
     870        3548 :       max_file_num = file_num;
     871        3548 :       max_file = res_file;
     872        3548 :       max_prefix = file_prefix;
     873             :     }
     874        5640 :   }
     875             : 
     876             :   // Error if nothing was located
     877        3212 :   if (max_file_num == -1)
     878           8 :     mooseError("No checkpoint file found!");
     879             : 
     880        6408 :   return max_prefix;
     881        3204 : }
     882             : 
     883             : bool
     884    25309596 : wildCardMatch(std::string name, std::string search_string)
     885             : {
     886             :   // Assume that an empty string matches anything
     887    25309596 :   if (search_string == "")
     888    23762572 :     return true;
     889             : 
     890             :   // transform to lower for case insenstive matching
     891     1547024 :   std::transform(name.begin(), name.end(), name.begin(), (int (*)(int))std::toupper);
     892     1547024 :   std::transform(search_string.begin(),
     893             :                  search_string.end(),
     894             :                  search_string.begin(),
     895             :                  (int (*)(int))std::toupper);
     896             : 
     897             :   // exact match!
     898     1547024 :   if (search_string.find("*") == std::string::npos)
     899     1547024 :     return search_string == name;
     900             : 
     901             :   // wildcard
     902           0 :   std::vector<std::string> tokens;
     903           0 :   MooseUtils::tokenize(search_string, tokens, 1, "*");
     904             : 
     905           0 :   size_t pos = 0;
     906           0 :   for (unsigned int i = 0; i < tokens.size() && pos != std::string::npos; ++i)
     907             :   {
     908           0 :     pos = name.find(tokens[i], pos);
     909             :     // See if we have a leading wildcard
     910           0 :     if (search_string[0] != '*' && i == 0 && pos != 0)
     911           0 :       return false;
     912             :   }
     913             : 
     914           0 :   if (pos != std::string::npos && tokens.size() > 0)
     915             :   {
     916             :     // Now see if we have a trailing wildcard
     917           0 :     size_t last_token_length = tokens.back().length();
     918           0 :     if (*search_string.rbegin() == '*' || pos == name.size() - last_token_length)
     919           0 :       return true;
     920             :     else
     921           0 :       return false;
     922             :   }
     923             :   else
     924           0 :     return false;
     925           0 : }
     926             : 
     927             : bool
     928       39371 : globCompare(const std::string & candidate,
     929             :             const std::string & pattern,
     930             :             std::size_t c,
     931             :             std::size_t p)
     932             : {
     933       39371 :   if (p == pattern.size())
     934        1816 :     return c == candidate.size();
     935             : 
     936       37555 :   if (pattern[p] == '*')
     937             :   {
     938       17734 :     for (; c < candidate.size(); ++c)
     939       16958 :       if (globCompare(candidate, pattern, c, p + 1))
     940         170 :         return true;
     941         776 :     return globCompare(candidate, pattern, c, p + 1);
     942             :   }
     943             : 
     944       36609 :   if (pattern[p] != '?' && pattern[p] != candidate[c])
     945       23874 :     return false;
     946             : 
     947       12735 :   return globCompare(candidate, pattern, c + 1, p + 1);
     948             : }
     949             : 
     950             : template <typename T>
     951             : T
     952        5038 : convertStringToInt(const std::string & str, bool throw_on_failure)
     953             : {
     954             :   T val;
     955             : 
     956             :   // Let's try to read a double and see if we can cast it to an int
     957             :   // This would be the case for scientific notation
     958             :   long double double_val;
     959        5038 :   std::stringstream double_ss(str);
     960        5038 :   double_ss >> double_val;
     961             : 
     962             :   // on arm64 the long double does not have sufficient precission
     963        5038 :   bool use_int = false;
     964        5038 :   std::stringstream int_ss(str);
     965        5038 :   if (!(int_ss >> val).fail() && int_ss.eof())
     966        4537 :     use_int = true;
     967             : 
     968        5038 :   if (double_ss.fail() || !double_ss.eof())
     969             :   {
     970         968 :     std::string msg =
     971         968 :         std::string("Unable to convert '") + str + "' to type " + demangle(typeid(T).name());
     972             : 
     973         484 :     if (throw_on_failure)
     974         478 :       throw std::invalid_argument(msg);
     975             :     else
     976           6 :       mooseError(msg);
     977         480 :   }
     978             : 
     979             :   // Check to see if it's an integer (and within range of an integer)
     980        4554 :   if (double_val == static_cast<long double>(static_cast<T>(double_val)))
     981        9080 :     return use_int ? val : static_cast<T>(double_val);
     982             : 
     983             :   // Still failure
     984          28 :   std::string msg =
     985          28 :       std::string("Unable to convert '") + str + "' to type " + demangle(typeid(T).name());
     986             : 
     987          14 :   if (throw_on_failure)
     988          14 :     throw std::invalid_argument(msg);
     989             :   else
     990           0 :     mooseError(msg);
     991        5542 : }
     992             : 
     993             : template <>
     994             : short int
     995         782 : convert<short int>(const std::string & str, bool throw_on_failure)
     996             : {
     997         782 :   return convertStringToInt<short int>(str, throw_on_failure);
     998             : }
     999             : 
    1000             : template <>
    1001             : unsigned short int
    1002        1969 : convert<unsigned short int>(const std::string & str, bool throw_on_failure)
    1003             : {
    1004        1969 :   return convertStringToInt<unsigned short int>(str, throw_on_failure);
    1005             : }
    1006             : 
    1007             : template <>
    1008             : int
    1009         531 : convert<int>(const std::string & str, bool throw_on_failure)
    1010             : {
    1011         531 :   return convertStringToInt<int>(str, throw_on_failure);
    1012             : }
    1013             : 
    1014             : template <>
    1015             : unsigned int
    1016        1540 : convert<unsigned int>(const std::string & str, bool throw_on_failure)
    1017             : {
    1018        1540 :   return convertStringToInt<unsigned int>(str, throw_on_failure);
    1019             : }
    1020             : 
    1021             : template <>
    1022             : long int
    1023           7 : convert<long int>(const std::string & str, bool throw_on_failure)
    1024             : {
    1025           7 :   return convertStringToInt<long int>(str, throw_on_failure);
    1026             : }
    1027             : 
    1028             : template <>
    1029             : unsigned long int
    1030         149 : convert<unsigned long int>(const std::string & str, bool throw_on_failure)
    1031             : {
    1032         149 :   return convertStringToInt<unsigned long int>(str, throw_on_failure);
    1033             : }
    1034             : 
    1035             : template <>
    1036             : long long int
    1037           7 : convert<long long int>(const std::string & str, bool throw_on_failure)
    1038             : {
    1039           7 :   return convertStringToInt<long long int>(str, throw_on_failure);
    1040             : }
    1041             : 
    1042             : template <>
    1043             : unsigned long long int
    1044          53 : convert<unsigned long long int>(const std::string & str, bool throw_on_failure)
    1045             : {
    1046          53 :   return convertStringToInt<unsigned long long int>(str, throw_on_failure);
    1047             : }
    1048             : 
    1049             : std::string
    1050     5111741 : stringJoin(const std::vector<std::string> & values, const std::string & separator)
    1051             : {
    1052     5111741 :   std::string combined;
    1053    12465134 :   for (const auto & value : values)
    1054     7353393 :     combined += value + separator;
    1055     5111741 :   if (values.size())
    1056     5102918 :     combined = combined.substr(0, combined.size() - separator.size());
    1057     5111741 :   return combined;
    1058           0 : }
    1059             : 
    1060             : bool
    1061     1104095 : beginsWith(const std::string & value, const std::string & begin_value)
    1062             : {
    1063     1104095 :   return value.rfind(begin_value, 0) == 0;
    1064             : }
    1065             : 
    1066             : ExecFlagEnum
    1067    17287706 : getDefaultExecFlagEnum()
    1068             : {
    1069    17287706 :   return moose::internal::ExecFlagRegistry::getExecFlagRegistry().getDefaultFlags();
    1070             : }
    1071             : 
    1072             : int
    1073         420 : stringToInteger(const std::string & input, bool throw_on_failure)
    1074             : {
    1075         420 :   return convert<int>(input, throw_on_failure);
    1076             : }
    1077             : 
    1078             : void
    1079         883 : linearPartitionItems(dof_id_type num_items,
    1080             :                      dof_id_type num_chunks,
    1081             :                      dof_id_type chunk_id,
    1082             :                      dof_id_type & num_local_items,
    1083             :                      dof_id_type & local_items_begin,
    1084             :                      dof_id_type & local_items_end)
    1085             : {
    1086         883 :   auto global_num_local_items = num_items / num_chunks;
    1087             : 
    1088         883 :   num_local_items = global_num_local_items;
    1089             : 
    1090         883 :   auto leftovers = num_items % num_chunks;
    1091             : 
    1092         883 :   if (chunk_id < leftovers)
    1093             :   {
    1094          36 :     num_local_items++;
    1095          36 :     local_items_begin = num_local_items * chunk_id;
    1096             :   }
    1097             :   else
    1098         847 :     local_items_begin =
    1099         847 :         (global_num_local_items + 1) * leftovers + global_num_local_items * (chunk_id - leftovers);
    1100             : 
    1101         883 :   local_items_end = local_items_begin + num_local_items;
    1102         883 : }
    1103             : 
    1104             : processor_id_type
    1105      396098 : linearPartitionChunk(dof_id_type num_items, dof_id_type num_chunks, dof_id_type item_id)
    1106             : {
    1107      396098 :   auto global_num_local_items = num_items / num_chunks;
    1108             : 
    1109      396098 :   auto leftovers = num_items % num_chunks;
    1110             : 
    1111      396098 :   auto first_item_past_first_part = leftovers * (global_num_local_items + 1);
    1112             : 
    1113             :   // Is it in the first section (that gets an extra item)
    1114      396098 :   if (item_id < first_item_past_first_part)
    1115         481 :     return item_id / (global_num_local_items + 1);
    1116             :   else
    1117             :   {
    1118      395617 :     auto new_item_id = item_id - first_item_past_first_part;
    1119             : 
    1120             :     // First chunk after the first section + the number of chunks after that
    1121      395617 :     return leftovers + (new_item_id / global_num_local_items);
    1122             :   }
    1123             : }
    1124             : 
    1125             : std::vector<std::string>
    1126      263716 : split(const std::string & str, const std::string & delimiter, std::size_t max_count)
    1127             : {
    1128      263716 :   std::vector<std::string> output;
    1129      263716 :   std::size_t count = 0;
    1130      263716 :   size_t prev = 0, pos = 0;
    1131             :   do
    1132             :   {
    1133      277585 :     pos = str.find(delimiter, prev);
    1134      277585 :     output.push_back(str.substr(prev, pos - prev));
    1135      277585 :     prev = pos + delimiter.length();
    1136      277585 :     count += 1;
    1137      277585 :   } while (pos != std::string::npos && count < max_count);
    1138             : 
    1139      263716 :   if (pos != std::string::npos)
    1140           1 :     output.push_back(str.substr(prev));
    1141             : 
    1142      263716 :   return output;
    1143           0 : }
    1144             : 
    1145             : std::vector<std::string>
    1146        9793 : rsplit(const std::string & str, const std::string & delimiter, std::size_t max_count)
    1147             : {
    1148        9793 :   std::vector<std::string> output;
    1149        9793 :   std::size_t count = 0;
    1150        9793 :   size_t prev = str.length(), pos = str.length();
    1151             :   do
    1152             :   {
    1153       16745 :     pos = str.rfind(delimiter, prev);
    1154       16745 :     output.insert(output.begin(), str.substr(pos + delimiter.length(), prev - pos));
    1155       16745 :     prev = pos - delimiter.length();
    1156       16745 :     count += 1;
    1157       16745 :   } while (pos != std::string::npos && pos > 0 && count < max_count);
    1158             : 
    1159        9793 :   if (pos != std::string::npos)
    1160           2 :     output.insert(output.begin(), str.substr(0, pos));
    1161             : 
    1162        9793 :   return output;
    1163           0 : }
    1164             : 
    1165             : void
    1166         163 : createSymlink(const std::string & target, const std::string & link)
    1167             : {
    1168         163 :   clearSymlink(link);
    1169             : #ifndef __WIN32__
    1170         163 :   auto err = symlink(target.c_str(), link.c_str());
    1171             : #else
    1172             :   auto err = CreateSymbolicLink(target.c_str(), link.c_str(), 0);
    1173             : #endif
    1174         163 :   if (err)
    1175           0 :     mooseError("Failed to create symbolic link (via 'symlink') from ", target, " to ", link);
    1176         163 : }
    1177             : 
    1178             : void
    1179        5224 : clearSymlink(const std::string & link)
    1180             : {
    1181             : #ifndef __WIN32__
    1182             :   struct stat sbuf;
    1183        5224 :   if (lstat(link.c_str(), &sbuf) == 0)
    1184             :   {
    1185         130 :     auto err = unlink(link.c_str());
    1186         130 :     if (err != 0)
    1187           0 :       mooseError("Failed to remove symbolic link (via 'unlink') to ", link);
    1188             :   }
    1189             : #else
    1190             :   auto attr = GetFileAttributesA(link.c_str());
    1191             :   if (attr != INVALID_FILE_ATTRIBUTES)
    1192             :   {
    1193             :     auto err = _unlink(link.c_str());
    1194             :     if (err != 0)
    1195             :       mooseError("Failed to remove link/file (via '_unlink') to ", link);
    1196             :   }
    1197             : #endif
    1198        5224 : }
    1199             : 
    1200             : std::size_t
    1201      129701 : fileSize(const std::string & filename)
    1202             : {
    1203             : #ifndef __WIN32__
    1204             :   struct stat buffer;
    1205      129701 :   if (!stat(filename.c_str(), &buffer))
    1206      129701 :     return buffer.st_size;
    1207             : #else
    1208             :   HANDLE hFile = CreateFile(filename.c_str(),
    1209             :                             GENERIC_READ,
    1210             :                             FILE_SHARE_READ | FILE_SHARE_WRITE,
    1211             :                             NULL,
    1212             :                             OPEN_EXISTING,
    1213             :                             FILE_ATTRIBUTE_NORMAL,
    1214             :                             NULL);
    1215             :   if (hFile == INVALID_HANDLE_VALUE)
    1216             :     return 0;
    1217             : 
    1218             :   LARGE_INTEGER size;
    1219             :   if (GetFileSizeEx(hFile, &size))
    1220             :   {
    1221             :     CloseHandle(hFile);
    1222             :     return size.QuadPart;
    1223             :   }
    1224             : 
    1225             :   CloseHandle(hFile);
    1226             : #endif
    1227           0 :   return 0;
    1228             : }
    1229             : 
    1230             : std::string
    1231       67334 : realpath(const std::string & path)
    1232             : {
    1233      134668 :   return std::filesystem::absolute(path);
    1234             : }
    1235             : 
    1236             : BoundingBox
    1237        7611 : buildBoundingBox(const Point & p1, const Point & p2)
    1238             : {
    1239        7611 :   BoundingBox bb;
    1240        7611 :   bb.union_with(p1);
    1241        7611 :   bb.union_with(p2);
    1242        7611 :   return bb;
    1243             : }
    1244             : 
    1245             : std::string
    1246     6820658 : prettyCppType(const std::string & cpp_type)
    1247             : {
    1248             :   // On mac many of the std:: classes are inline namespaced with __1
    1249             :   // On linux std::string can be inline namespaced with __cxx11
    1250     6820658 :   std::string s = cpp_type;
    1251             :   // Remove all spaces surrounding a >
    1252     6820658 :   pcrecpp::RE("\\s(?=>)").GlobalReplace("", &s);
    1253     6820658 :   pcrecpp::RE("std::__\\w+::").GlobalReplace("std::", &s);
    1254             :   // It would be nice if std::string actually looked normal
    1255     6820658 :   pcrecpp::RE("\\s*std::basic_string<char, std::char_traits<char>, std::allocator<char>>\\s*")
    1256     6820658 :       .GlobalReplace("std::string", &s);
    1257             :   // It would be nice if std::vector looked normal
    1258     6820658 :   pcrecpp::RE r("std::vector<([[:print:]]+),\\s?std::allocator<\\s?\\1\\s?>\\s?>");
    1259     6820658 :   r.GlobalReplace("std::vector<\\1>", &s);
    1260             :   // Do it again for nested vectors
    1261     6820658 :   r.GlobalReplace("std::vector<\\1>", &s);
    1262    13641316 :   return s;
    1263     6820658 : }
    1264             : 
    1265             : std::string
    1266       68002 : canonicalPath(const std::string & path)
    1267             : {
    1268      136004 :   return std::filesystem::weakly_canonical(path).c_str();
    1269             : }
    1270             : 
    1271             : bool
    1272           0 : startsWith(const std::string & string1, const std::string & string2)
    1273             : {
    1274           0 :   if (string2.size() > string1.size())
    1275           0 :     return false;
    1276           0 :   return string1.compare(0, string2.size(), string2) == 0;
    1277             : }
    1278             : 
    1279             : void
    1280           0 : replaceStart(std::string & string1, const std::string & string2, const std::string & string3)
    1281             : {
    1282             :   mooseAssert(startsWith(string1, string2),
    1283             :               "Cannot replace the start because it doesn't match the start string");
    1284           0 :   string1.replace(0, string2.size(), string3);
    1285           0 : }
    1286             : 
    1287             : bool
    1288           0 : isAllLowercase(const std::string & str)
    1289             : {
    1290           0 :   return std::all_of(
    1291           0 :       str.begin(), str.end(), [](unsigned char c) { return !std::isalpha(c) || std::islower(c); });
    1292             : }
    1293             : } // MooseUtils namespace
    1294             : 
    1295             : void
    1296       82336 : removeSubstring(std::string & main, const std::string & sub)
    1297             : {
    1298       82336 :   std::string::size_type n = sub.length();
    1299       82336 :   for (std::string::size_type i = main.find(sub); i != std::string::npos; i = main.find(sub))
    1300           0 :     main.erase(i, n);
    1301       82336 : }
    1302             : 
    1303             : std::string
    1304      307007 : removeSubstring(const std::string & main, const std::string & sub)
    1305             : {
    1306      307007 :   std::string copy_main = main;
    1307      307007 :   std::string::size_type n = sub.length();
    1308      614014 :   for (std::string::size_type i = copy_main.find(sub); i != std::string::npos;
    1309      307007 :        i = copy_main.find(sub))
    1310      307007 :     copy_main.erase(i, n);
    1311      307007 :   return copy_main;
    1312           0 : }

Generated by: LCOV version 1.14