LCOV - code coverage report
Current view: top level - src/utils - MooseUtils.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 502 605 83.0 %
Date: 2025-07-17 01:28:37 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      130245 : pathjoin(const std::filesystem::path & p)
      60             : {
      61      130245 :   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        2473 : parsesToReal(const std::string & input)
      90             : {
      91        2473 :   std::istringstream ss(input);
      92             :   Real real_value;
      93        2473 :   if (ss >> real_value && ss.eof())
      94        1819 :     return true;
      95         654 :   return false;
      96        2473 : }
      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    19544988 : mooseDocsURL(const std::string & path)
     136             : {
     137    19544988 :   return "https://mooseframework.inl.gov/" + path;
     138             : }
     139             : 
     140             : std::string
     141      215255 : replaceAll(std::string str, const std::string & from, const std::string & to)
     142             : {
     143      215255 :   size_t start_pos = 0;
     144      216006 :   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      215255 :   return str;
     150             : }
     151             : 
     152             : std::string
     153        3370 : convertLatestCheckpoint(std::string orig)
     154             : {
     155        3370 :   auto slash_pos = orig.find_last_of("/");
     156        3370 :   auto path = orig.substr(0, slash_pos);
     157        3370 :   auto file = orig.substr(slash_pos + 1);
     158        3370 :   if (file != "LATEST")
     159        3079 :     return orig;
     160             : 
     161         291 :   auto converted = MooseUtils::getLatestCheckpointFilePrefix(MooseUtils::listDir(path));
     162             : 
     163         291 :   if (converted.empty())
     164           0 :     mooseError("Unable to find suitable recovery file!");
     165             : 
     166         291 :   return converted;
     167        3370 : }
     168             : 
     169             : // this implementation is copied from
     170             : // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C.2B.2B
     171             : int
     172        3623 : 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        3623 :   auto s1len = s1.size();
     177        3623 :   auto s2len = s2.size();
     178             : 
     179        3623 :   auto column_start = (decltype(s1len))1;
     180             : 
     181        3623 :   auto column = new decltype(s1len)[s1len + 1];
     182        3623 :   std::iota(column + column_start, column + s1len + 1, column_start);
     183             : 
     184       35935 :   for (auto x = column_start; x <= s2len; x++)
     185             :   {
     186       32312 :     column[0] = x;
     187       32312 :     auto last_diagonal = x - column_start;
     188      411673 :     for (auto y = column_start; y <= s1len; y++)
     189             :     {
     190      379361 :       auto old_diagonal = column[y];
     191      379361 :       auto possibilities = {
     192      379361 :           column[y] + 1, column[y - 1] + 1, last_diagonal + (s1[y - 1] == s2[x - 1] ? 0 : 1)};
     193      379361 :       column[y] = std::min(possibilities);
     194      379361 :       last_diagonal = old_diagonal;
     195             :     }
     196             :   }
     197        3623 :   auto result = column[s1len];
     198        3623 :   delete[] column;
     199        3623 :   return result;
     200             : }
     201             : 
     202             : void
     203     7104971 : escape(std::string & str)
     204             : {
     205     7104971 :   std::map<char, std::string> escapes;
     206     7104971 :   escapes['\a'] = "\\a";
     207     7104971 :   escapes['\b'] = "\\b";
     208     7104971 :   escapes['\f'] = "\\f";
     209     7104971 :   escapes['\n'] = "\\n";
     210     7104971 :   escapes['\t'] = "\\t";
     211     7104971 :   escapes['\v'] = "\\v";
     212     7104971 :   escapes['\r'] = "\\r";
     213             : 
     214    56839768 :   for (const auto & it : escapes)
     215    49734953 :     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     7104971 : }
     219             : 
     220             : std::string
     221      444935 : removeExtraWhitespace(const std::string & input)
     222             : {
     223      889870 :   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       22740 : pathExists(const std::string & path)
     244             : {
     245             :   struct stat buffer;
     246       22740 :   return (stat(path.c_str(), &buffer) == 0);
     247             : }
     248             : 
     249             : bool
     250      328723 : checkFileReadable(const std::string & filename,
     251             :                   bool check_line_endings,
     252             :                   bool throw_on_unreadable,
     253             :                   bool check_for_git_lfs_pointer)
     254             : {
     255      328723 :   std::ifstream in(filename.c_str(), std::ifstream::in);
     256      328723 :   if (in.fail())
     257             :   {
     258       67224 :     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       67207 :       return false;
     265             :   }
     266             : 
     267      261499 :   if (check_line_endings)
     268             :   {
     269       62440 :     std::istream_iterator<char> iter(in);
     270       62440 :     std::istream_iterator<char> eos;
     271       62440 :     in >> std::noskipws;
     272    76355988 :     while (iter != eos)
     273    76293548 :       if (*iter++ == '\r')
     274           0 :         mooseError(filename + " contains Windows(DOS) line endings which are not supported.");
     275             :   }
     276             : 
     277      261499 :   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      261491 :   in.close();
     281             : 
     282      261491 :   return true;
     283      328699 : }
     284             : 
     285             : bool
     286      198462 : checkForGitLFSPointer(std::ifstream & file)
     287             : {
     288             :   mooseAssert(file.is_open(), "Passed in file handle is not open");
     289             : 
     290      198462 :   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      198462 :   file.seekg(0);
     295      198462 :   std::getline(file, line);
     296      198462 :   if (line.find("version https://") != std::string::npos)
     297           8 :     return true;
     298             :   else
     299      198454 :     return false;
     300      198462 : }
     301             : 
     302             : bool
     303         240 : checkFileWriteable(const std::string & filename, bool throw_on_unwritable)
     304             : {
     305         240 :   std::ofstream out(filename.c_str(), std::ios_base::app);
     306         240 :   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         240 :   out.close();
     318             : 
     319         240 :   return true;
     320         240 : }
     321             : 
     322             : void
     323      240442 : parallelBarrierNotify(const Parallel::Communicator & comm, bool messaging)
     324             : {
     325             :   processor_id_type secondary_processor_id;
     326             : 
     327      240442 :   if (messaging)
     328           0 :     Moose::out << "Waiting For Other Processors To Finish" << std::endl;
     329      240442 :   if (comm.rank() == 0)
     330             :   {
     331             :     // The primary process is already through, so report it
     332      173928 :     if (messaging)
     333           0 :       Moose::out << "Jobs complete: 1/" << comm.size() << (1 == comm.size() ? "\n" : "\r")
     334           0 :                  << std::flush;
     335      240442 :     for (unsigned int i = 2; i <= comm.size(); ++i)
     336             :     {
     337       66514 :       comm.receive(MPI_ANY_SOURCE, secondary_processor_id);
     338       66514 :       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       66514 :     secondary_processor_id = comm.rank();
     346       66514 :     comm.send(0, secondary_processor_id);
     347             :   }
     348             : 
     349      240442 :   comm.barrier();
     350      240442 : }
     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       23813 : hasExtension(const std::string & filename, std::string ext, bool strip_exodus_ext)
     384             : {
     385             :   // Extract the extension, w/o the '.'
     386       23813 :   std::string file_ext;
     387       23813 :   if (strip_exodus_ext)
     388             :   {
     389             :     pcrecpp::RE re(
     390         570 :         ".*\\.([^\\.]*?)(?:-s\\d+)?\\s*$"); // capture the complete extension, ignoring -s*
     391         570 :     re.FullMatch(filename, &file_ext);
     392         570 :   }
     393             :   else
     394             :   {
     395       23243 :     pcrecpp::RE re(".*\\.([^\\.]*?)\\s*$"); // capture the complete extension
     396       23243 :     re.FullMatch(filename, &file_ext);
     397       23243 :   }
     398             : 
     399             :   // Perform the comparision
     400       23813 :   if (file_ext == ext)
     401       12710 :     return true;
     402             :   else
     403       11103 :     return false;
     404       23813 : }
     405             : 
     406             : std::string
     407         623 : getExtension(const std::string & filename, const bool rfind)
     408             : {
     409         623 :   std::string file_ext = "";
     410         623 :   if (filename != "")
     411             :   {
     412             :     // The next line splits filename at the last "/" and gives the file name after "/"
     413         611 :     const std::string stripped_filename = splitFileName<std::string>(filename).second;
     414         611 :     auto pos = rfind ? stripped_filename.rfind(".") : stripped_filename.find(".");
     415         611 :     if (pos != std::string::npos)
     416         185 :       file_ext += stripped_filename.substr(pos + 1, std::string::npos);
     417         611 :   }
     418             : 
     419         623 :   return file_ext;
     420           0 : }
     421             : 
     422             : std::string
     423         251 : stripExtension(const std::string & s, const bool rfind)
     424             : {
     425         251 :   const std::string ext = getExtension(s, rfind);
     426         251 :   const bool offset = (ext.size() != 0);
     427             :   // -1 offset accounts for the extension's leading dot ("."), if there is an extension
     428         502 :   return s.substr(0, s.size() - ext.size() - offset);
     429         251 : }
     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         510 : underscoreToCamelCase(const std::string & underscore_name, bool leading_upper_case)
     577             : {
     578         510 :   pcrecpp::StringPiece input(underscore_name);
     579         510 :   pcrecpp::RE re("([^_]*)(_|$)");
     580             : 
     581         510 :   std::string result;
     582         510 :   std::string us, not_us;
     583         510 :   bool make_upper = leading_upper_case;
     584         522 :   while (re.Consume(&input, &not_us, &us))
     585             :   {
     586         522 :     if (not_us.length() > 0)
     587             :     {
     588         516 :       if (make_upper)
     589             :       {
     590         514 :         result += std::toupper(not_us[0]);
     591         514 :         if (not_us.length() > 1)
     592         514 :           result += not_us.substr(1);
     593             :       }
     594             :       else
     595           2 :         result += not_us;
     596             :     }
     597         522 :     if (us == "")
     598         510 :       break;
     599             : 
     600             :     // Toggle flag so next match is upper cased
     601          12 :     make_upper = true;
     602             :   }
     603             : 
     604        1020 :   return result;
     605         510 : }
     606             : 
     607             : std::string
     608     4426663 : shortName(const std::string & name)
     609             : {
     610     4426663 :   return name.substr(name.find_last_of('/') != std::string::npos ? name.find_last_of('/') + 1 : 0);
     611             : }
     612             : 
     613             : std::string
     614     1388297 : baseName(const std::string & name)
     615             : {
     616     1388297 :   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      121815 : 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      121815 :   w.ws_col = std::numeric_limits<unsigned short>::max();
     651             : 
     652      121815 :   if (use_environment)
     653             :   {
     654      121815 :     char * pps_width = std::getenv("MOOSE_PPS_WIDTH");
     655      121815 :     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      121815 :   if (w.ws_col == std::numeric_limits<unsigned short>::max())
     663             :   {
     664             : #ifndef __WIN32__
     665             :     try
     666             :     {
     667      121815 :       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      121815 :   if (w.ws_col == std::numeric_limits<unsigned short>::max())
     678      121815 :     w.ws_col = 132;
     679             : 
     680      121815 :   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       19527 : removeColor(std::string & msg)
     719             : {
     720       19527 :   pcrecpp::RE re("(\\33\\[3[0-7]m))", pcrecpp::DOTALL());
     721       19527 :   re.GlobalReplace(std::string(""), &msg);
     722       19527 :   return msg;
     723       19527 : }
     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     1254755 : 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     1254755 :   std::string colored_message;
     746     1254755 :   std::string curr_color = COLOR_DEFAULT; // tracks last color code before newline
     747     1254755 :   std::string line, color_code;
     748             : 
     749     1254755 :   bool ends_in_newline = message.empty() ? true : message.back() == '\n';
     750             : 
     751     1254755 :   bool first = true;
     752             : 
     753     1254755 :   std::istringstream iss(message);
     754     3175135 :   for (std::string line; std::getline(iss, line);) // loop over each line
     755             :   {
     756     1920380 :     const static pcrecpp::RE match_color(".*(\\33\\[3\\dm)((?!\\33\\[3\\d)[^\n])*");
     757     1920380 :     pcrecpp::StringPiece line_piece(line);
     758     1920380 :     match_color.FindAndConsume(&line_piece, &color_code);
     759             : 
     760     1920380 :     if (!first || indent_first_line)
     761     1920380 :       colored_message += color + prefix + post_prefix + curr_color;
     762             : 
     763     1920380 :     colored_message += line;
     764             : 
     765             :     // Only add a newline to the last line if it had one to begin with!
     766     1920380 :     if (!iss.eof() || ends_in_newline)
     767     1856970 :       colored_message += "\n";
     768             : 
     769     1920380 :     if (!color_code.empty())
     770      897709 :       curr_color = color_code; // remember last color of this line
     771             : 
     772     1920380 :     first = false;
     773     1254755 :   }
     774     1254755 :   message = colored_message;
     775     1254755 : }
     776             : 
     777             : std::list<std::string>
     778        3235 : listDir(const std::string path, bool files_only)
     779             : {
     780        3235 :   std::list<std::string> files;
     781             : 
     782        3235 :   tinydir_dir dir;
     783        3235 :   dir.has_next = 0; // Avoid a garbage value in has_next (clang StaticAnalysis)
     784        3235 :   tinydir_open(&dir, path.c_str());
     785             : 
     786       20380 :   while (dir.has_next)
     787             :   {
     788             :     tinydir_file file;
     789       17145 :     file.is_dir = 0; // Avoid a garbage value in is_dir (clang StaticAnalysis)
     790       17145 :     tinydir_readfile(&dir, &file);
     791             : 
     792       17145 :     if (!files_only || !file.is_dir)
     793       17145 :       files.push_back(path + "/" + file.name);
     794             : 
     795       17145 :     tinydir_next(&dir);
     796             :   }
     797             : 
     798        3235 :   tinydir_close(&dir);
     799             : 
     800        6470 :   return files;
     801           0 : }
     802             : 
     803             : std::list<std::string>
     804        2892 : getFilesInDirs(const std::list<std::string> & directory_list, const bool files_only /* = true */)
     805             : {
     806        2892 :   std::list<std::string> files;
     807             : 
     808        5818 :   for (const auto & dir_name : directory_list)
     809        2926 :     files.splice(files.end(), listDir(dir_name, files_only));
     810             : 
     811        2892 :   return files;
     812           0 : }
     813             : 
     814             : std::string
     815        3183 : 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        3183 :   std::time_t newest_time = 0;
     821        3183 :   std::list<std::string> newest_restart_files;
     822             : 
     823             :   // Loop through all possible files and store the newest
     824       20234 :   for (const auto & cp_file : checkpoint_files)
     825             :   {
     826       17051 :     if (MooseUtils::hasExtension(cp_file, "rd"))
     827             :     {
     828             :       struct stat stats;
     829        6292 :       stat(cp_file.c_str(), &stats);
     830             : 
     831        6292 :       std::time_t mod_time = stats.st_mtime;
     832        6292 :       if (mod_time > newest_time)
     833             :       {
     834        3295 :         newest_restart_files.clear(); // If the modification time is greater, clear the list
     835        3295 :         newest_time = mod_time;
     836             :       }
     837             : 
     838        6292 :       if (mod_time == newest_time)
     839        5883 :         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        3183 :   int max_file_num = -1;
     845        3183 :   std::string max_file;
     846        3183 :   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        3183 :   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        8871 :   for (const auto & res_file : newest_restart_files)
     856             :   {
     857        5688 :     int file_num = 0;
     858             : 
     859             :     // All of the file up to and including the digits
     860        5688 :     std::string file_prefix;
     861             : 
     862        5688 :     re_file_num.FullMatch(res_file, &file_prefix, &file_num);
     863             : 
     864        5688 :     if (file_num > max_file_num)
     865             :     {
     866             :       // Need both the header and the data
     867        3332 :       if (!RestartableDataReader::isAvailable(res_file))
     868           0 :         continue;
     869             : 
     870        3332 :       max_file_num = file_num;
     871        3332 :       max_file = res_file;
     872        3332 :       max_prefix = file_prefix;
     873             :     }
     874        5688 :   }
     875             : 
     876             :   // Error if nothing was located
     877        3183 :   if (max_file_num == -1)
     878           8 :     mooseError("No checkpoint file found!");
     879             : 
     880        6350 :   return max_prefix;
     881        3175 : }
     882             : 
     883             : bool
     884    23342958 : wildCardMatch(std::string name, std::string search_string)
     885             : {
     886             :   // Assume that an empty string matches anything
     887    23342958 :   if (search_string == "")
     888    21801980 :     return true;
     889             : 
     890             :   // transform to lower for case insenstive matching
     891     1540978 :   std::transform(name.begin(), name.end(), name.begin(), (int (*)(int))std::toupper);
     892     1540978 :   std::transform(search_string.begin(),
     893             :                  search_string.end(),
     894             :                  search_string.begin(),
     895             :                  (int (*)(int))std::toupper);
     896             : 
     897             :   // exact match!
     898     1540978 :   if (search_string.find("*") == std::string::npos)
     899     1540978 :     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       35871 : globCompare(const std::string & candidate,
     929             :             const std::string & pattern,
     930             :             std::size_t c,
     931             :             std::size_t p)
     932             : {
     933       35871 :   if (p == pattern.size())
     934        1670 :     return c == candidate.size();
     935             : 
     936       34201 :   if (pattern[p] == '*')
     937             :   {
     938       16220 :     for (; c < candidate.size(); ++c)
     939       15510 :       if (globCompare(candidate, pattern, c, p + 1))
     940         156 :         return true;
     941         710 :     return globCompare(candidate, pattern, c, p + 1);
     942             :   }
     943             : 
     944       33335 :   if (pattern[p] != '?' && pattern[p] != candidate[c])
     945       21670 :     return false;
     946             : 
     947       11665 :   return globCompare(candidate, pattern, c + 1, p + 1);
     948             : }
     949             : 
     950             : template <typename T>
     951             : T
     952        4690 : 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        4690 :   std::stringstream double_ss(str);
     960        4690 :   double_ss >> double_val;
     961             : 
     962             :   // on arm64 the long double does not have sufficient precission
     963        4690 :   bool use_int = false;
     964        4690 :   std::stringstream int_ss(str);
     965        4690 :   if (!(int_ss >> val).fail() && int_ss.eof())
     966        4226 :     use_int = true;
     967             : 
     968        4690 :   if (double_ss.fail() || !double_ss.eof())
     969             :   {
     970         894 :     std::string msg =
     971         894 :         std::string("Unable to convert '") + str + "' to type " + demangle(typeid(T).name());
     972             : 
     973         447 :     if (throw_on_failure)
     974         441 :       throw std::invalid_argument(msg);
     975             :     else
     976           6 :       mooseError(msg);
     977         443 :   }
     978             : 
     979             :   // Check to see if it's an integer (and within range of an integer)
     980        4243 :   if (double_val == static_cast<long double>(static_cast<T>(double_val)))
     981        8458 :     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        5157 : }
     992             : 
     993             : template <>
     994             : short int
     995         708 : convert<short int>(const std::string & str, bool throw_on_failure)
     996             : {
     997         708 :   return convertStringToInt<short int>(str, throw_on_failure);
     998             : }
     999             : 
    1000             : template <>
    1001             : unsigned short int
    1002        1856 : convert<unsigned short int>(const std::string & str, bool throw_on_failure)
    1003             : {
    1004        1856 :   return convertStringToInt<unsigned short int>(str, throw_on_failure);
    1005             : }
    1006             : 
    1007             : template <>
    1008             : int
    1009         498 : convert<int>(const std::string & str, bool throw_on_failure)
    1010             : {
    1011         498 :   return convertStringToInt<int>(str, throw_on_failure);
    1012             : }
    1013             : 
    1014             : template <>
    1015             : unsigned int
    1016        1425 : convert<unsigned int>(const std::string & str, bool throw_on_failure)
    1017             : {
    1018        1425 :   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         138 : convert<unsigned long int>(const std::string & str, bool throw_on_failure)
    1031             : {
    1032         138 :   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          51 : convert<unsigned long long int>(const std::string & str, bool throw_on_failure)
    1045             : {
    1046          51 :   return convertStringToInt<unsigned long long int>(str, throw_on_failure);
    1047             : }
    1048             : 
    1049             : std::string
    1050     4681952 : stringJoin(const std::vector<std::string> & values, const std::string & separator)
    1051             : {
    1052     4681952 :   std::string combined;
    1053    11444929 :   for (const auto & value : values)
    1054     6762977 :     combined += value + separator;
    1055     4681952 :   if (values.size())
    1056     4673833 :     combined = combined.substr(0, combined.size() - separator.size());
    1057     4681952 :   return combined;
    1058           0 : }
    1059             : 
    1060             : bool
    1061     1119810 : beginsWith(const std::string & value, const std::string & begin_value)
    1062             : {
    1063     1119810 :   return value.rfind(begin_value, 0) == 0;
    1064             : }
    1065             : 
    1066             : ExecFlagEnum
    1067    16955876 : getDefaultExecFlagEnum()
    1068             : {
    1069    16955876 :   return moose::internal::ExecFlagRegistry::getExecFlagRegistry().getDefaultFlags();
    1070             : }
    1071             : 
    1072             : int
    1073         394 : stringToInteger(const std::string & input, bool throw_on_failure)
    1074             : {
    1075         394 :   return convert<int>(input, throw_on_failure);
    1076             : }
    1077             : 
    1078             : void
    1079         802 : 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         802 :   auto global_num_local_items = num_items / num_chunks;
    1087             : 
    1088         802 :   num_local_items = global_num_local_items;
    1089             : 
    1090         802 :   auto leftovers = num_items % num_chunks;
    1091             : 
    1092         802 :   if (chunk_id < leftovers)
    1093             :   {
    1094          33 :     num_local_items++;
    1095          33 :     local_items_begin = num_local_items * chunk_id;
    1096             :   }
    1097             :   else
    1098         769 :     local_items_begin =
    1099         769 :         (global_num_local_items + 1) * leftovers + global_num_local_items * (chunk_id - leftovers);
    1100             : 
    1101         802 :   local_items_end = local_items_begin + num_local_items;
    1102         802 : }
    1103             : 
    1104             : processor_id_type
    1105      356534 : linearPartitionChunk(dof_id_type num_items, dof_id_type num_chunks, dof_id_type item_id)
    1106             : {
    1107      356534 :   auto global_num_local_items = num_items / num_chunks;
    1108             : 
    1109      356534 :   auto leftovers = num_items % num_chunks;
    1110             : 
    1111      356534 :   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      356534 :   if (item_id < first_item_past_first_part)
    1115         429 :     return item_id / (global_num_local_items + 1);
    1116             :   else
    1117             :   {
    1118      356105 :     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      356105 :     return leftovers + (new_item_id / global_num_local_items);
    1122             :   }
    1123             : }
    1124             : 
    1125             : std::vector<std::string>
    1126      262897 : split(const std::string & str, const std::string & delimiter, std::size_t max_count)
    1127             : {
    1128      262897 :   std::vector<std::string> output;
    1129      262897 :   std::size_t count = 0;
    1130      262897 :   size_t prev = 0, pos = 0;
    1131             :   do
    1132             :   {
    1133      275459 :     pos = str.find(delimiter, prev);
    1134      275459 :     output.push_back(str.substr(prev, pos - prev));
    1135      275459 :     prev = pos + delimiter.length();
    1136      275459 :     count += 1;
    1137      275459 :   } while (pos != std::string::npos && count < max_count);
    1138             : 
    1139      262897 :   if (pos != std::string::npos)
    1140           1 :     output.push_back(str.substr(prev));
    1141             : 
    1142      262897 :   return output;
    1143           0 : }
    1144             : 
    1145             : std::vector<std::string>
    1146        9082 : rsplit(const std::string & str, const std::string & delimiter, std::size_t max_count)
    1147             : {
    1148        9082 :   std::vector<std::string> output;
    1149        9082 :   std::size_t count = 0;
    1150        9082 :   size_t prev = str.length(), pos = str.length();
    1151             :   do
    1152             :   {
    1153       15509 :     pos = str.rfind(delimiter, prev);
    1154       15509 :     output.insert(output.begin(), str.substr(pos + delimiter.length(), prev - pos));
    1155       15509 :     prev = pos - delimiter.length();
    1156       15509 :     count += 1;
    1157       15509 :   } while (pos != std::string::npos && pos > 0 && count < max_count);
    1158             : 
    1159        9082 :   if (pos != std::string::npos)
    1160           2 :     output.insert(output.begin(), str.substr(0, pos));
    1161             : 
    1162        9082 :   return output;
    1163           0 : }
    1164             : 
    1165             : void
    1166         145 : createSymlink(const std::string & target, const std::string & link)
    1167             : {
    1168         145 :   clearSymlink(link);
    1169             : #ifndef __WIN32__
    1170         145 :   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         145 :   if (err)
    1175           0 :     mooseError("Failed to create symbolic link (via 'symlink') from ", target, " to ", link);
    1176         145 : }
    1177             : 
    1178             : void
    1179        4734 : clearSymlink(const std::string & link)
    1180             : {
    1181             : #ifndef __WIN32__
    1182             :   struct stat sbuf;
    1183        4734 :   if (lstat(link.c_str(), &sbuf) == 0)
    1184             :   {
    1185         113 :     auto err = unlink(link.c_str());
    1186         113 :     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        4734 : }
    1199             : 
    1200             : std::size_t
    1201      116387 : fileSize(const std::string & filename)
    1202             : {
    1203             : #ifndef __WIN32__
    1204             :   struct stat buffer;
    1205      116387 :   if (!stat(filename.c_str(), &buffer))
    1206      116387 :     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       62465 : realpath(const std::string & path)
    1232             : {
    1233      124930 :   return std::filesystem::absolute(path);
    1234             : }
    1235             : 
    1236             : BoundingBox
    1237        7036 : buildBoundingBox(const Point & p1, const Point & p2)
    1238             : {
    1239        7036 :   BoundingBox bb;
    1240        7036 :   bb.union_with(p1);
    1241        7036 :   bb.union_with(p2);
    1242        7036 :   return bb;
    1243             : }
    1244             : 
    1245             : std::string
    1246     6786982 : 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     6786982 :   std::string s = cpp_type;
    1251             :   // Remove all spaces surrounding a >
    1252     6786982 :   pcrecpp::RE("\\s(?=>)").GlobalReplace("", &s);
    1253     6786982 :   pcrecpp::RE("std::__\\w+::").GlobalReplace("std::", &s);
    1254             :   // It would be nice if std::string actually looked normal
    1255     6786982 :   pcrecpp::RE("\\s*std::basic_string<char, std::char_traits<char>, std::allocator<char>>\\s*")
    1256     6786982 :       .GlobalReplace("std::string", &s);
    1257             :   // It would be nice if std::vector looked normal
    1258     6786982 :   pcrecpp::RE r("std::vector<([[:print:]]+),\\s?std::allocator<\\s?\\1\\s?>\\s?>");
    1259     6786982 :   r.GlobalReplace("std::vector<\\1>", &s);
    1260             :   // Do it again for nested vectors
    1261     6786982 :   r.GlobalReplace("std::vector<\\1>", &s);
    1262    13573964 :   return s;
    1263     6786982 : }
    1264             : 
    1265             : std::string
    1266       63182 : canonicalPath(const std::string & path)
    1267             : {
    1268      126364 :   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       76552 : removeSubstring(std::string & main, const std::string & sub)
    1297             : {
    1298       76552 :   std::string::size_type n = sub.length();
    1299       76552 :   for (std::string::size_type i = main.find(sub); i != std::string::npos; i = main.find(sub))
    1300           0 :     main.erase(i, n);
    1301       76552 : }
    1302             : 
    1303             : std::string
    1304      285627 : removeSubstring(const std::string & main, const std::string & sub)
    1305             : {
    1306      285627 :   std::string copy_main = main;
    1307      285627 :   std::string::size_type n = sub.length();
    1308      571254 :   for (std::string::size_type i = copy_main.find(sub); i != std::string::npos;
    1309      285627 :        i = copy_main.find(sub))
    1310      285627 :     copy_main.erase(i, n);
    1311      285627 :   return copy_main;
    1312           0 : }

Generated by: LCOV version 1.14