LCOV - code coverage report
Current view: top level - libMagAOX/file - fileTimes.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 98.2 % 112 110
Test Date: 2026-01-03 21:03:39 Functions: 100.0 % 7 7

            Line data    Source code
       1              : /** \file fileTimes.hpp
       2              :  * \brief Utilities for working with file timestamps
       3              :  * \ingroup file_files
       4              :  */
       5              : 
       6              : #ifndef file_fileTimes_hpp
       7              : #define file_fileTimes_hpp
       8              : 
       9              : #include <time.h>
      10              : #include <cstring>
      11              : #include <iostream>
      12              : #include <format>
      13              : 
      14              : #include <mx/mxlib.hpp>
      15              : 
      16              : #include "../common/defaults.hpp"
      17              : 
      18              : #include "../common/exceptions.hpp"
      19              : 
      20              : namespace MagAOX
      21              : {
      22              : namespace file
      23              : {
      24              : 
      25              : #ifdef XWCTEST_NAMESPACE
      26              : namespace XWCTEST_NAMESPACE
      27              : {
      28              : #endif
      29              : 
      30              : /// Get the filename timestamp from the breakdown for a time.
      31              : /** Fills in the \p tstamp string with the timestamp encoded as
      32              :  * \verbatim
      33              :  *      YYYYMMDDHHMMSSNNNNNNNNN
      34              :  * \endverbatim
      35              :  *
      36              :  * \returns mx::error_t::noerror on success
      37              :  * \returns mx::error_t::format_error if std::format throws and exception
      38              :  * \returns mx::error_t::std_exception if any other exception other than bad_alloc is caught
      39              :  *
      40              :  * \returns throws nested mx::exception if std::bad_alloc is caught from std::format
      41              :  *
      42              :  */
      43              : template <class verboseT = XWC_DEFAULT_VERBOSITY>
      44          352 : mx::error_t timestamp( std::string &tstamp, /**< [out] the timestamp string*/
      45              :                        const tm    &uttime, /**< [in] the broken down time*/
      46              :                        long         ts_nsec /**< [in] the nanosecond*/
      47              : )
      48              : {
      49              :     try
      50              :     {
      51              : 
      52              :         // clang-format off
      53              :         #ifdef XWCTEST_TIMESTAMP_THROW_BAD_ALLOC
      54              :         throw std::bad_alloc(); // LCOV_EXCL_LINE
      55              :         #endif
      56              :         // clang-format on
      57              : 
      58              :         // clang-format off
      59              :         #ifdef XWCTEST_TIMESTAMP_THROW_FORMAT_ERROR
      60              :         throw std::format_error("testing format_error"); // LCOV_EXCL_LINE
      61              :         #endif
      62              :         // clang-format on
      63              : 
      64              :         // clang-format off
      65              :         #ifdef XWCTEST_TIMESTAMP_THROW_EXCEPTION
      66              :         throw std::exception(); // LCOV_EXCL_LINE
      67              :         #endif
      68              :         // clang-format on
      69              : 
      70          343 :         tstamp = std::format( "{:04}{:02}{:02}{:02}{:02}{:02}{:09}",
      71            0 :                               uttime.tm_year + 1900,
      72            0 :                               uttime.tm_mon + 1,
      73          343 :                               uttime.tm_mday,
      74          343 :                               uttime.tm_hour,
      75          343 :                               uttime.tm_min,
      76          343 :                               uttime.tm_sec,
      77              :                               ts_nsec );
      78              :     }
      79           12 :     catch( const std::bad_alloc &e )
      80              :     {
      81           12 :         std::throw_with_nested( mx::exception<verboseT>(mx::error_t::std_bad_alloc, "from std::format") );
      82              :     }
      83            6 :     catch( const std::format_error &e )
      84              :     {
      85            6 :         return mx::error_report<verboseT>( mx::error_t::std_format_error,
      86           15 :                                            std::string( "from std::format: " ) + e.what() );
      87              :     }
      88            6 :     catch( const std::exception &e )
      89              :     {
      90            9 :         return mx::error_report<verboseT>( mx::error_t::std_exception, std::string( "from std::format: " ) + e.what() );
      91              :     }
      92              : 
      93          343 :     return mx::error_t::noerror;
      94              : }
      95              : 
      96              : /// Get the filename timestamp and the breakdown for a time.
      97              : /** Fills in the \p tstamp string with the timestamp encoded as
      98              :  * \verbatim
      99              :  *      YYYYMMDDHHMMSSNNNNNNNNN
     100              :  * \endverbatim
     101              :  * and the broken down `tm` structure \p uttime
     102              :  *
     103              :  * \returns mx::error_t::noerror on success
     104              :  * \returns mx::error_t::eoverflow if year is too big for gmtime_r
     105              :  * \returns mx::error_t::error if gmtime_r returns an error without setting errno
     106              :  * \returns mx::error_t::format_error if std::format throws and exception
     107              :  * \returns mx::error_t::std_exception if any other exception other than bad_alloc is caught in \ref
     108              :  * timestamp(std::string &, const tm&, long) "timestamp"
     109              :  *
     110              :  * \returns throws nested mx::exception if an exception is caught from \ref timestamp(std::string &, const tm&, long)
     111              :  * "timestamp" , which means std::bad_alloc was thrown
     112              :  *
     113              :  */
     114              : template <typename verboseT = XWC_DEFAULT_VERBOSITY>
     115          356 : mx::error_t timestamp( std::string &tstamp, /**< [out] the timestamp string*/
     116              :                        tm          &uttime, /**< [out] the broken down time*/
     117              :                        time_t       ts_sec, /**< [in] the unix time second*/
     118              :                        long         ts_nsec /**< [in] the nanosecond*/
     119              : )
     120              : {
     121          356 :     memset( &uttime, 0, sizeof( uttime ) );
     122              : 
     123          356 :     errno = 0;
     124          356 :     if( gmtime_r( &ts_sec, &uttime ) == 0 )
     125              :     {
     126              :         // clang-format off
     127              :         #ifdef XWCTEST_TIMESTAMP_GMTIME_OTHER
     128              :         errno = 0; // LCOV_EXCL_LINE
     129              :         #endif
     130              :         // clang-format on
     131              : 
     132            4 :         if( errno != 0 )
     133              :         {
     134            9 :             return mx::error_report<verboseT>( mx::errno2error_t( errno ),
     135            3 :                                                "error getting UT time (gmtime_r returned 0)" );
     136              :         }
     137              :         else
     138              :         {
     139            2 :             return mx::error_report<verboseT>( mx::error_t::error, "error getting UT time (gmtime_r returned 0)" );
     140              :         }
     141              :     }
     142              : 
     143              :     try
     144              :     {
     145          352 :         mx_error_return( timestamp<verboseT>( tstamp, uttime, ts_nsec ) );
     146              :     }
     147            6 :     catch( ... )
     148              :     {
     149            6 :         std::throw_with_nested( mx::exception<verboseT>(mx::error_t::exception) );
     150              :     }
     151              : }
     152              : 
     153              : /// Get the filename timestamp for a time.
     154              : /** Fills in the \p tstamp string with the timestamp encoded as
     155              :  * \verbatim
     156              :  * YYYYMMDDHHMMSSNNNNNNNNN
     157              :  * \endverbatim
     158              :  *
     159              :  * \overload
     160              :  *
     161              :  * \returns mx::error_t::noerror on success
     162              :  * \returns mx::error_t::eoverflow if year is too big for gmtime_r
     163              :  * \returns mx::error_t::error if gmtime_r returns an error without setting errno
     164              :  * \returns mx::error_t::std_exception if an exception other than bad_alloc is caught in \ref timestamp(std::string &,
     165              :  * const tm&, long) "timestamp"
     166              :  *
     167              :  * \returns throws nested mx::exception if an exception is caught from \ref timestamp(std::string &, const tm&, long)
     168              :  * "timestamp" , which means std::bad_alloc was thrown
     169              :  *
     170              :  */
     171              : template <class verboseT = XWC_DEFAULT_VERBOSITY>
     172            4 : mx::error_t timestamp( std::string &tstamp, /**< [out] the timestamp string*/
     173              :                        time_t       ts_sec, /**< [in] the unix time second*/
     174              :                        long         ts_nsec /**< [in] the nanosecond*/
     175              : )
     176              : {
     177              :     tm uttime;
     178            4 :     memset( &uttime, 0, sizeof( uttime ) );
     179              : 
     180              :     try
     181              :     {
     182            4 :         mx_error_return( timestamp<verboseT>( tstamp, uttime, ts_sec, ts_nsec ) );
     183              :     }
     184            2 :     catch( ... )
     185              :     {
     186            2 :         std::throw_with_nested( mx::exception<verboseT>( mx::error_t::exception));
     187              :     }
     188              : }
     189              : 
     190              : /// Get the timestamp and the relative path based on a time
     191              : /**  Fills in the \p tstamp string with the timestamp encoded as
     192              :  * \verbatim
     193              :  *      YYYYMMDDHHMMSSNNNNNNNNN
     194              :  * \endverbatim
     195              :  * and the \p relPath string with the format
     196              :  * \verbatim
     197              :  *      yyyy_mm_dd
     198              :  * \endverbatim
     199              :  *
     200              :  * \returns 0 on success
     201              :  * \returns -1 if gmtime_r returns an error (from \ref timestamp)
     202              :  * \returns -2 if snprintf returns an error writing tstamp (from \ref timestamp)
     203              :  * \returns -3 if snprintf does not write enough characters to tstamp (from \ref timestamp)
     204              :  * \returns -4 if snprintf returns an error writing relPath
     205              :  * \returns -5 if snprintf does not write enough characters to relPath
     206              :  *
     207              :  */
     208              : template <class verboseT = XWC_DEFAULT_VERBOSITY>
     209          347 : mx::error_t fileTimeRelPath( std::string &tstamp,  /**< [out] */
     210              :                              std::string &relPath, /**< [out] */
     211              :                              time_t       ts_sec,  /**< [in] the unix time second*/
     212              :                              long         ts_nsec  /**< [in] the nanosecond*/
     213              : )
     214              : {
     215          347 :     if(ts_sec == 0 && ts_nsec == 0)
     216              :     {
     217            2 :         return mx::error_report<verboseT>( mx::error_t::invalidarg, "all 0 time");
     218              :     }
     219              : 
     220              :     tm uttime;
     221          346 :     memset( &uttime, 0, sizeof( uttime ) );
     222              : 
     223              :     try
     224              :     {
     225              :         // clang-format off
     226              :         #ifdef XWCTEST_FILETIMERELPATH_THROW_BAD_ALLOC
     227              :         throw std::bad_alloc(); // LCOV_EXCL_LINE
     228              :         #endif
     229              :         // clang-format on
     230              : 
     231              :         // clang-format off
     232              :         #ifdef XWCTEST_FILETIMERELPATH_THROW_FORMAT_ERROR
     233              :         throw std::format_error("testing format_error"); // LCOV_EXCL_LINE
     234              :         #endif
     235              :         // clang-format on
     236              : 
     237              :         // clang-format off
     238              :         #ifdef XWCTEST_FILETIMERELPATH_THROW_EXCEPTION
     239              :         throw std::exception(); // LCOV_EXCL_LINE
     240              :         #endif
     241              :         // clang-format on
     242              : 
     243          343 :         mx_error_check( timestamp<verboseT>( tstamp, uttime, ts_sec, ts_nsec ) );
     244              : 
     245          339 :         relPath = std::format( "{:04}_{:02}_{:02}", uttime.tm_year + 1900, uttime.tm_mon + 1, uttime.tm_mday );
     246              : 
     247          339 :         return mx::error_t::noerror;
     248              :     }
     249            5 :     catch( const std::bad_alloc &e )
     250              :     {
     251            4 :         std::throw_with_nested( mx::exception<verboseT>(mx::error_t::std_bad_alloc, "getting relPath") );
     252              :     }
     253            2 :     catch( const mx::exception<verboseT> & e ) // This is from previous bad_alloc
     254              :     {
     255            4 :         std::throw_with_nested( mx::exception<verboseT>(e.code(), "getting relPath") );
     256              :     }
     257            2 :     catch( const std::format_error &e )
     258              :     {
     259            2 :         return mx::error_report<verboseT>( mx::error_t::std_format_error,
     260            5 :                                            std::string( "from std::format: " ) + e.what() );
     261              :     }
     262            2 :     catch( const std::exception &e )
     263              :     {
     264            2 :         return mx::error_report<verboseT>( mx::error_t::std_exception, e.what() );
     265              :     }
     266              : 
     267              : }
     268              : 
     269              : /// Construct the filename and full relative path based on a time and a device name and extension
     270              : /**  Fills in the fileName string with the timestamp encoded as
     271              :  * \verbatim
     272              :  *      devName_YYYYMMDDHHMMSSNNNNNNNNN.ext
     273              :  * \endverbatim
     274              :  * and the \p relPath string with the format
     275              :  * \verbatim
     276              :  *      devName/YYYY_MM_DD
     277              :  * \endverbatim
     278              :  *
     279              :  * \overload
     280              :  *
     281              :  * \returns mx::error_t::noerror on success
     282              :  * \returns errors from fileTimeRelPath(std::string&,std::string&, time_t, long)
     283              :  * \returns mx::error_t::std_exception if an exception other than std::bad_alloc is caught
     284              :  * \throws nested mx::excpetion if std::bad_alloc is thrown
     285              :  */
     286              : template <class verboseT = XWC_DEFAULT_VERBOSITY>
     287          347 : mx::error_t fileTimeRelPath( std::string       &fileName, /**< [out] the resulting file name*/
     288              :                              std::string       &relPath,  /**< [out] the resulting relative path*/
     289              :                              const std::string &devName,  /**< [in] the device name part of the path.  No '/'. */
     290              :                              const std::string &ext,      /**< [in] the extension part of the filename. No `.`. */
     291              :                              time_t             ts_sec,   /**< [in] the unix time second*/
     292              :                              long               ts_nsec   /**< [in] the nanosecond*/
     293              : )
     294              : {
     295          347 :     std::string tstamp, tmprelpath;
     296              : 
     297              :     try
     298              :     {
     299          347 :         mx_error_check( fileTimeRelPath<verboseT>( tstamp, tmprelpath, ts_sec, ts_nsec ) );
     300              :     }
     301            4 :     catch( ... ) // This is from previous bad_alloc
     302              :     {
     303            4 :         std::throw_with_nested( mx::exception<verboseT>(mx::error_t::exception));
     304              :     }
     305              : 
     306              :     try
     307              :     {
     308              :         // clang-format off
     309              :         #ifdef XWCTEST_FILETIMERELPATHSTRING_THROW_BAD_ALLOC
     310              :         throw std::bad_alloc(); // LCOV_EXCL_LINE
     311              :         #endif
     312              :         // clang-format on
     313              : 
     314              :         // clang-format off
     315              :         #ifdef XWCTEST_FILETIMERELPATHSTRING_THROW_EXCEPTION
     316              :         throw std::exception(); // LCOV_EXCL_LINE
     317              :         #endif
     318              :         // clang-format on
     319              : 
     320          337 :         relPath  = devName + '/' + tmprelpath;
     321          337 :         fileName = devName + '_' + tstamp + '.' + ext;
     322              : 
     323          337 :         return mx::error_t::noerror;
     324              :     }
     325            3 :     catch( const std::bad_alloc &e )
     326              :     {
     327            4 :         std::throw_with_nested( mx::exception<verboseT>(mx::error_t::std_bad_alloc, "std::string assembling paths" ) );
     328              :     }
     329            2 :     catch( const std::exception &e )
     330              :     {
     331            2 :         return mx::error_report<verboseT>( mx::error_t::std_exception,
     332            5 :                                            std::string( "std::string assembling paths" ) + e.what() );
     333              :     }
     334          350 : }
     335              : 
     336              : /// Parse a standard XWCTk timestamp string
     337              : /** Extracts the date components.
     338              :  *
     339              :  * The input must be exactly 23 characters long.
     340              :  *
     341              :  * No validity checks are done on the components.
     342              :  *
     343              :  * \returns mx::error_t::noerror on success
     344              :  * \returns mx::error_t::invalidarg if timestamp is not 23 characters long
     345              :  * \returns mx::error_t::std_out_of_range if std::out_of_range is thrown by std::substr
     346              :  * \returns mx::error_t::exception if any other exception other than bad_alloc is thrown by std::string::substr
     347              :  *
     348              :  * \throws nested mx::exception if std::bad_alloc is thrown
     349              :  *
     350              :  */
     351              : template <class verboseT = XWC_DEFAULT_VERBOSITY>
     352          111 : mx::error_t parseTimestamp( std::string       &YYYY,  /**< [out] the 4 digit year*/
     353              :                             std::string       &MM,    /**< [out] the 2 digit month*/
     354              :                             std::string       &DD,    /**< [out] the 2 digit day*/
     355              :                             std::string       &hh,    /**< [out] the 2 digit hour*/
     356              :                             std::string       &mm,    /**< [out] the 2 digit minute*/
     357              :                             std::string       &ss,    /**< [out] the 2 digit second*/
     358              :                             std::string       &nn,    /**< [out] the 9 digit nanosecond*/
     359              :                             const std::string &tstamp /**< [in] the 23-digit timestamp */
     360              : )
     361              : {
     362              :     try
     363              :     {
     364              :         // clang-format off
     365              :         #ifdef XWCTEST_PARSETIMESTAMP_THROW_BAD_ALLOC
     366              :         throw std::bad_alloc(); // LCOV_EXCL_LINE
     367              :         #endif
     368              :         // clang-format on
     369              : 
     370              :         // clang-format off
     371              :         #ifdef XWCTEST_PARSETIMESTAMP_THROW_OUT_OF_RANGE
     372              :         throw std::out_of_range("testing out of range"); // LCOV_EXCL_LINE
     373              :         #endif
     374              :         // clang-format on
     375              : 
     376              :         // clang-format off
     377              :         #ifdef XWCTEST_PARSETIMESTAMP_THROW_EXCEPTION
     378              :         throw std::exception(); // LCOV_EXCL_LINE
     379              :         #endif
     380              :         // clang-format on
     381              : 
     382          108 :         if( tstamp.length() != 23 )
     383              :         {
     384            4 :             return mx::error_report<verboseT>( mx::error_t::invalidarg, "timestamp does not have 23 characters" );
     385              :         }
     386              : 
     387          106 :         YYYY = tstamp.substr( 0, 4 );
     388          106 :         MM   = tstamp.substr( 4, 2 );
     389          106 :         DD   = tstamp.substr( 6, 2 );
     390          106 :         hh   = tstamp.substr( 8, 2 );
     391          106 :         mm   = tstamp.substr( 10, 2 );
     392          106 :         ss   = tstamp.substr( 12, 2 );
     393          106 :         nn   = tstamp.substr( 14, 9 );
     394              : 
     395          106 :         return mx::error_t::noerror;
     396              :     }
     397            4 :     catch( const std::bad_alloc &e )
     398              :     {
     399            2 :         std::throw_with_nested( mx::exception<verboseT>(mx::error_t::std_bad_alloc));
     400              :     }
     401            2 :     catch( const std::out_of_range &e )
     402              :     {
     403            2 :         return mx::error_report<verboseT>( mx::error_t::std_out_of_range,
     404            5 :                                            std::string( "parsing timestamp" ) + e.what() );
     405              :     }
     406            2 :     catch( const std::exception &e )
     407              :     {
     408            3 :         return mx::error_report<verboseT>( mx::error_t::std_exception, std::string( "parsing timestamp" ) + e.what() );
     409              :     }
     410              : }
     411              : 
     412              : /// Parse a standard XWCTk timestamp filepath
     413              : /** Extracts the device name and the date components.
     414              :  * The only restriction on the input \fname is that it be at least 23 characters long.
     415              :  * In this case it contains only the timestamp.
     416              :  *
     417              :  * No validity checks are done on the components (i.e. no check that the timestamp
     418              :  * is all numeric, no check on device name format).
     419              :  *
     420              :  * Examples of valid inputs are:
     421              :  * - `device_20241121063300000000000.txt`
     422              :  * - `/path/to/device_20241121063300000000000.txt`
     423              :  * - `20241121063300000000000`
     424              :  *
     425              :  * \returns 0 on success
     426              :  * \returns -1 on error
     427              :  *
     428              :  */
     429              : template <class verboseT = XWC_DEFAULT_VERBOSITY>
     430          116 : mx::error_t parseFilePath( std::string       &devName, /**< [out] the device name */
     431              :                            std::string       &YYYY,    /**< [out] the 4 digit year*/
     432              :                            std::string       &MM,      /**< [out] the 2 digit month*/
     433              :                            std::string       &DD,      /**< [out] the 2 digit day*/
     434              :                            std::string       &hh,      /**< [out] the 2 digit hour*/
     435              :                            std::string       &mm,      /**< [out] the 2 digit minute*/
     436              :                            std::string       &ss,      /**< [out] the 2 digit second*/
     437              :                            std::string       &nn,      /**< [out] the 9 digit nanosecond*/
     438              :                            const std::string &fname    /**< [in] the filename, which can include a path */
     439              : )
     440              : {
     441              :     try
     442              :     {
     443              :         // clang-format off
     444              :         #ifdef XWCTEST_PARSEFILEPATH_THROW_BAD_ALLOC
     445              :         throw std::bad_alloc(); // LCOV_EXCL_LINE
     446              :         #endif
     447              :         // clang-format on
     448              : 
     449              :         // clang-format off
     450              :         #ifdef XWCTEST_PARSEFILEPATH_THROW_EXCEPTION
     451              :         throw std::exception(); // LCOV_EXCL_LINE
     452              :         #endif
     453              :         // clang-format on
     454              : 
     455          113 :         size_t est = fname.rfind( '.' ); // rfind does not throw
     456          113 :         if( est == std::string::npos )
     457              :         {
     458            6 :             est = fname.size(); // no extension
     459              :         }
     460              : 
     461              :         size_t dst;
     462              :         size_t dend;
     463              : 
     464          113 :         dend = fname.rfind( '_', est ); // rfind does not throw
     465              : 
     466          113 :         if( dend == std::string::npos ) // no device name, just a timestamp
     467              :         {
     468              : 
     469            4 :             dst = fname.rfind( '/', est );
     470              : 
     471            4 :             if( dst == std::string::npos ) // no path
     472              :             {
     473            2 :                 dst = 0;
     474              :             }
     475              :             else
     476              :             {
     477            2 :                 ++dst; // move past the '/'
     478              :             }
     479              : 
     480            4 :             dend = est;
     481              : 
     482            4 :             devName = "";
     483              :         }
     484              :         else
     485              :         {
     486              : 
     487          109 :             dst = fname.rfind( '/', dend );
     488              : 
     489          109 :             if( dst == std::string::npos ) // no path
     490              :             {
     491           99 :                 dst = 0;
     492              :             }
     493              :             else
     494              :             {
     495           10 :                 ++dst; // move past the '/'
     496              :             }
     497              : 
     498          109 :             if( dst >= dend ) // This is '/_YYYY....'
     499              :             {
     500            4 :                 devName = ""; // no device
     501              :             }
     502              :             else // finally, we have a device name
     503              :             {
     504              : 
     505              :                 // clang-format off
     506              :                 #ifdef XWCTEST_PARSEFILEPATH_THROW_OUT_OF_RANGE
     507              :                 throw std::out_of_range("testing out of range"); // LCOV_EXCL_LINE
     508              :                 #endif
     509              :                 // clang-format on
     510              : 
     511          103 :                 devName = fname.substr( dst, dend - dst );
     512              :             }
     513              : 
     514          107 :             dst  = dend + 1; // now move to beginning of timestamp
     515          107 :             dend = est;      // and one-past-the-end of the timestamp
     516              :         }
     517              : 
     518              :         // Here dst...dend should be just the timestamp
     519          111 :         if( dend - dst != 23 )
     520              :         {
     521            4 :             return mx::error_report<verboseT>( mx::error_t::invalidarg, "timestamp does not have 23 characters" );
     522              :         }
     523              : 
     524              :         // clang-format off
     525              :         #ifdef XWCTEST_PARSEFILEPATH_TOO_SHORT
     526              :         // this will generate a too-short error at this point (invalidarg)
     527              :         ++dst; // LCOV_EXCL_LINE
     528              :         #endif
     529              :         // clang-format on
     530              : 
     531          110 :         mx_error_return( parseTimestamp<verboseT>( YYYY, MM, DD, hh, mm, ss, nn, fname.substr( dst, dend - dst ) ) );
     532              :     }
     533            8 :     catch( const std::bad_alloc &e )
     534              :     {
     535            8 :         std::throw_with_nested( mx::exception<verboseT>(mx::error_t::std_bad_alloc, "parsing filepath") );
     536              :     }
     537            2 :     catch( const mx::exception<verboseT> &e ) // from a previous bad_alloc
     538              :     {
     539            4 :         std::throw_with_nested( mx::exception<verboseT>(e.code(), "parsing filepath") );
     540              :     }
     541            4 :     catch( const std::out_of_range &e )
     542              :     {
     543            4 :         return mx::error_report<verboseT>( mx::error_t::std_out_of_range, e.what() );
     544              :     }
     545            2 :     catch( const std::exception &e )
     546              :     {
     547            2 :         return mx::error_report<verboseT>( mx::error_t::std_exception, e.what() );
     548              :     }
     549              : 
     550              : }
     551              : 
     552              : #ifdef XWCTEST_NAMESPACE
     553              : }
     554              : #endif
     555              : 
     556              : } // namespace file
     557              : } // namespace MagAOX
     558              : 
     559              : #endif // file_fileTimes_hpp
        

Generated by: LCOV version 2.0-1