8#ifndef file_stdSubDir_hpp 
    9#define file_stdSubDir_hpp 
   14#include <mx/mxlib.hpp> 
   15#include <mx/ioutils/stringUtils.hpp> 
   16#include "../common/exceptions.hpp" 
   18#include "../common/defaults.hpp" 
   25#ifdef XWCTEST_NAMESPACE 
   34template <
typename verboseT = XWC_DEFAULT_VERBOSITY>
 
   41    mutable bool m_pathMade{ 
false }; 
 
   45    bool m_valid{ 
false }; 
 
   57    explicit stdSubDir( 
const std::chrono::sys_days &sysday  );
 
   84    mx::error_t 
ymd( 
int      year,  
 
   93    mx::error_t 
path( 
const std::string &subdir );
 
  100    std::string 
path( mx::error_t *errc = 
nullptr  ) 
const;
 
  107    int year( mx::error_t *errc = 
nullptr  ) 
const;
 
  114    unsigned int month( mx::error_t *errc = 
nullptr  ) 
const;
 
  121    unsigned int day( mx::error_t *errc = 
nullptr  ) 
const;
 
  185template <
typename verboseT>
 
  191template <
typename verboseT>
 
  197        #ifdef XWCTEST_STDSUBDIR_CTORSYSDAYS_BAD_ALLOC 
  198            throw std::bad_alloc(); 
 
  201        #ifdef XWCTEST_STDSUBDIR_CTORSYSDAYS_EXCEPTION 
  202            throw std::exception(); 
 
  209    catch( 
const std::bad_alloc &e )
 
  211        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  213    catch( 
const std::exception &e )
 
  215        mx::error_report<verboseT>( mx::error_t::std_exception, std::string( 
"chrono operations: " ) + e.what() );
 
 
  219template <
typename verboseT>
 
  222    ymd( year, month, day );
 
 
  225template <
typename verboseT>
 
  231template <
typename verboseT>
 
  241        #ifdef XWCTEST_STDSUBDIR_YMD_BAD_ALLOC 
  242            throw std::bad_alloc(); 
 
  245        #ifdef XWCTEST_STDSUBDIR_YMD_EXCEPTION 
  246            throw std::exception(); 
 
  250        std::chrono::year_month_day ymd{
 
  251            std::chrono::year( year ), std::chrono::month( month ), std::chrono::day( day ) };
 
  256        return mx::error_t::noerror;
 
  258    catch( 
const std::bad_alloc &e )
 
  260        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  262    catch( 
const std::exception &e )
 
  264        return mx::error_report<verboseT>( mx::error_t::std_exception,
 
  265                                           std::string( 
"chrono operations: " ) + e.what() );
 
 
  269template <
typename verboseT>
 
  276    if( subdir.length() != 10 )
 
  278        return mx::error_report<verboseT>( mx::error_t::invalidarg, 
"subdir " + subdir + 
" is not 10 chars long " );
 
  281    for( 
size_t n : { 4, 7 } )
 
  283        if( subdir[n] != 
'_' )
 
  285            return mx::error_report<verboseT>( mx::error_t::invalidarg, 
"subdir " + subdir + 
" is missing _ " );
 
  289    for( 
size_t n : { 0, 1, 2, 3, 5, 6, 8, 9 } )
 
  291        if( !isdigit( subdir[n] ) )
 
  293            return mx::error_report<verboseT>( mx::error_t::invalidarg,
 
  294                                               "subdir " + subdir + 
" has non-digit at " + std::to_string( n ) );
 
  301    unsigned int month, day;
 
  306        #ifdef XWCTEST_STDSUBDIR_SETPATH_BAD_ALLOC 
  307            throw std::bad_alloc(); 
 
  310        #ifdef XWCTEST_STDSUBDIR_SETPATH_OUT_OF_RANGE 
  311            throw std::out_of_range(
"test"); 
 
  314        #ifdef XWCTEST_STDSUBDIR_SETPATH_EXCEPTION 
  315            throw std::exception(); 
 
  319        year = mx::ioutils::stoT<int>( subdir.substr( 0, 4 ), errc );
 
  320        mx_error_check_code( errc );
 
  322        month = mx::ioutils::stoT<unsigned int>( subdir.substr( 5, 2 ), errc );
 
  323        mx_error_check_code( errc );
 
  325        day = mx::ioutils::stoT<unsigned int>( subdir.substr( 8, 2 ), errc );
 
  326        mx_error_check_code( errc );
 
  328    catch( 
const std::bad_alloc &e )
 
  330        std::throw_with_nested( 
xwcException( 
"parsing subdir", -6 ) );
 
  332    catch( 
const std::out_of_range &e )
 
  334        return mx::error_report<verboseT>( mx::error_t::std_out_of_range, std::string( 
"parsing subdir" ) + e.what() );
 
  336    catch( 
const std::exception &e )
 
  338        return mx::error_report<verboseT>( mx::error_t::std_exception, std::string( 
"parsing subdir" ) + e.what() );
 
  344        #ifdef XWCTEST_STDSUBDIR_SETPATH_BAD_ALLOC2 
  345            throw std::bad_alloc(); 
 
  348        #ifdef XWCTEST_STDSUBDIR_SETPATH_EXCEPTION2 
  349            throw std::exception(); 
 
  353        std::chrono::year_month_day ymd{
 
  354            std::chrono::year( year ), std::chrono::month( month ), std::chrono::day( day ) };
 
  363        return mx::error_t::noerror;
 
  365    catch( 
const std::bad_alloc &e )
 
  367        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  369    catch( 
const std::exception &e )
 
  371        return mx::error_report<verboseT>( mx::error_t::std_exception,
 
  372                                           std::string( 
"chrono operations: " ) + e.what() );
 
 
  376template <
typename verboseT>
 
  383            *errc = mx::error_t::invalidconfig;
 
  385        mx::error_report<verboseT>( mx::error_t::invalidconfig, 
"attempt to access path while invalid" );
 
  394            #ifdef XWCTEST_STDSUBDIR_MAKEPATH_BAD_ALLOC 
  395                throw std::bad_alloc(); 
 
  398            #ifdef XWCTEST_STDSUBDIR_MAKEPATH_FORMAT_ERROR 
  399                throw std::format_error(
"test"); 
 
  402            #ifdef XWCTEST_STDSUBDIR_MAKEPATH_EXCEPTION 
  403                throw std::exception(); 
 
  407            m_path = std::format( 
"{:%Y_%m_%d}", m_sysday );
 
  411        catch( 
const std::bad_alloc &e )
 
  413            std::throw_with_nested( 
xwcException( 
"bad_alloc from std::format", -12 ) );
 
  415        catch( 
const std::format_error &e )
 
  419                *errc = mx::error_t::std_format_error;
 
  421            mx::error_report<verboseT>( mx::error_t::std_format_error, std::string( 
"from std::format: " ) + e.what() );
 
  424        catch( 
const std::exception &e )
 
  428                *errc = mx::error_t::std_exception;
 
  430            mx::error_report<verboseT>( mx::error_t::std_exception, std::string( 
"from std::format: " ) + e.what() );
 
  437        *errc = mx::error_t::noerror;
 
 
  442template <
typename verboseT>
 
  449            *errc = mx::error_t::invalidconfig;
 
  451        mx::error_report<verboseT>( mx::error_t::invalidconfig, 
"attempt to access year while invalid" );
 
  452        return std::numeric_limits<int>::max();
 
  458        #ifdef XWCTEST_STDSUBDIR_GYMD_BAD_ALLOC 
  459            throw std::bad_alloc(); 
 
  462        #ifdef XWCTEST_STDSUBDIR_GYMD_EXCEPTION 
  463            throw std::exception(); 
 
  467        std::chrono::year_month_day ymd{ m_sysday };
 
  471            *errc = mx::error_t::noerror;
 
  474        return static_cast<int>( ymd.year() );
 
  476    catch( 
const std::bad_alloc &e )
 
  480            *errc = mx::error_t::std_bad_alloc;
 
  482        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  484    catch( 
const std::exception &e )
 
  488            *errc = mx::error_t::std_exception;
 
  490        mx::error_report<verboseT>( mx::error_t::std_exception, std::string( 
"chrono operations: " ) + e.what() );
 
  491        return std::numeric_limits<int>::max();
 
 
  495template <
typename verboseT>
 
  502            *errc = mx::error_t::invalidconfig;
 
  504        mx::error_report<verboseT>( mx::error_t::invalidconfig, 
"attempt to access month while invalid" );
 
  505        return std::numeric_limits<unsigned int>::max();
 
  511        #ifdef XWCTEST_STDSUBDIR_GYMD_BAD_ALLOC 
  512            throw std::bad_alloc(); 
 
  515        #ifdef XWCTEST_STDSUBDIR_GYMD_EXCEPTION 
  516            throw std::exception(); 
 
  520        std::chrono::year_month_day ymd{ m_sysday };
 
  524            *errc = mx::error_t::noerror;
 
  526        return static_cast<unsigned>( ymd.month() );
 
  528    catch( 
const std::bad_alloc &e )
 
  532            *errc = mx::error_t::std_bad_alloc;
 
  534        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  536    catch( 
const std::exception &e )
 
  540            *errc = mx::error_t::std_exception;
 
  542        mx::error_report<verboseT>( mx::error_t::std_exception, std::string( 
"chrono operations: " ) + e.what() );
 
  543        return std::numeric_limits<unsigned int>::max();
 
 
  547template <
typename verboseT>
 
  554            *errc = mx::error_t::invalidconfig;
 
  556        mx::error_report<verboseT>( mx::error_t::invalidconfig, 
"attempt to access day while invalid" );
 
  557        return std::numeric_limits<unsigned int>::max();
 
  563        #ifdef XWCTEST_STDSUBDIR_GYMD_BAD_ALLOC 
  564            throw std::bad_alloc(); 
 
  567        #ifdef XWCTEST_STDSUBDIR_GYMD_EXCEPTION 
  568            throw std::exception(); 
 
  572        std::chrono::year_month_day ymd{ m_sysday };
 
  576            *errc = mx::error_t::noerror;
 
  578        return static_cast<unsigned>( ymd.day() );
 
  580    catch( 
const std::bad_alloc &e )
 
  584            *errc = mx::error_t::std_bad_alloc;
 
  586        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  588    catch( 
const std::exception &e )
 
  592            *errc = mx::error_t::std_exception;
 
  594        mx::error_report<verboseT>( mx::error_t::std_exception, std::string( 
"chrono operations: " ) + e.what() );
 
  595        return std::numeric_limits<unsigned int>::max();
 
 
  599template <
typename verboseT>
 
  605template <
typename verboseT>
 
  610        return mx::error_report<verboseT>( mx::error_t::invalidconfig, 
"attempt to access while invalid" );
 
  616        #ifdef XWCTEST_STDSUBDIR_INC_BAD_ALLOC 
  617            throw std::bad_alloc(); 
 
  620        #ifdef XWCTEST_STDSUBDIR_INC_EXCEPTION 
  621            throw std::exception(); 
 
  628    catch( 
const std::bad_alloc &e )
 
  631        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  633    catch( 
const std::exception &e )
 
  636        return mx::error_report<verboseT>( mx::error_t::std_exception,
 
  637                                           std::string( 
"chrono operations: " ) + e.what() );
 
  640    return mx::error_t::noerror;
 
 
  643template <
typename verboseT>
 
  648        return mx::error_report<verboseT>( mx::error_t::invalidconfig, 
"attempt to access while invalid" );
 
  654        #ifdef XWCTEST_STDSUBDIR_INC_BAD_ALLOC 
  655            throw std::bad_alloc(); 
 
  658        #ifdef XWCTEST_STDSUBDIR_INC_EXCEPTION 
  659            throw std::exception(); 
 
  667        return mx::error_t::noerror;
 
  669    catch( 
const std::bad_alloc &e )
 
  672        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  674    catch( 
const std::exception &e )
 
  677        return mx::error_report<verboseT>( mx::error_t::std_exception,
 
  678                                           std::string( 
"chrono operations: " ) + e.what() );
 
 
  682template <
typename verboseT>
 
  689            *errc = mx::error_t::invalidconfig;
 
  691        mx::error_report<verboseT>( mx::error_t::invalidconfig, 
"attempt to access while invalid" );
 
  698        #ifdef XWCTEST_STDSUBDIR_PREVFOLL_BAD_ALLOC 
  699            throw std::bad_alloc(); 
 
  706        #ifdef XWCTEST_STDSUBDIR_PREV_INVAL 
  716                *errc = mx::error_t::error;
 
  718            mx::error_report<verboseT>( mx::error_t::error, 
"an error occurred creating new subdir" );
 
  722        mx::error_t _errc = std.
subDay();
 
  724        if( _errc != mx::error_t::noerror )
 
  726            mx::error_report<verboseT>( _errc, 
"from subDay" );
 
  736    catch( 
const std::bad_alloc &e )
 
  740            *errc = mx::error_t::std_bad_alloc;
 
  742        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  748            *errc = mx::error_t::std_exception;
 
  750        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
 
  754template <
typename verboseT>
 
  761            *errc = mx::error_t::invalidconfig;
 
  763        mx::error_report<verboseT>( mx::error_t::invalidconfig, 
"attempt to access while invalid" );
 
  770        #ifdef XWCTEST_STDSUBDIR_PREVFOLL_BAD_ALLOC 
  771            throw std::bad_alloc(); 
 
  778        #ifdef XWCTEST_STDSUBDIR_PREV_INVAL 
  788                *errc = mx::error_t::error;
 
  790            mx::error_report<verboseT>( mx::error_t::error, 
"an error occurred creating new subdir" );
 
  794        mx::error_t _errc = std.
addDay();
 
  796        if( _errc != mx::error_t::noerror )
 
  798            mx::error_report<verboseT>( _errc, 
"from subDay" );
 
  808    catch( 
const std::bad_alloc &e )
 
  812            *errc = mx::error_t::std_bad_alloc;
 
  814        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
  820            *errc = mx::error_t::std_exception;
 
  822        std::throw_with_nested( 
xwcException( 
"chrono operations", -6 ) );
 
 
  826template <
typename verboseT>
 
  829    return ( m_sysday == comp.
m_sysday );
 
 
  832template <
typename verboseT>
 
  835    return ( m_sysday != comp.
m_sysday );
 
 
  838template <
typename verboseT>
 
  841    return ( m_sysday < comp.
m_sysday );
 
 
  844template <
typename verboseT>
 
  847    return ( m_sysday <= comp.
m_sysday );
 
 
  850template <
typename verboseT>
 
  853    return ( m_sysday > comp.
m_sysday );
 
 
  856template <
typename verboseT>
 
  859    return ( m_sysday >= comp.
m_sysday );
 
 
  862template <
typename verboseT>
 
 
  871#ifndef XWCTEST_NAMESPACE 
  875#ifdef XWCTEST_NAMESPACE 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Manage a standard subdirectory.
 
bool operator<(const stdSubDir &comp) const
Compare two subdirectories for less-than by timestamp.
 
mx::error_t ymd(int year, unsigned month, unsigned day)
Setup from components.
 
std::string m_path
The path string. Only constructed on demand.
 
stdSubDir(int year, unsigned month, unsigned day)
Construct from components.
 
unsigned int day(mx::error_t *errc=nullptr) const
Get the current value of m_day.
 
mx::error_t path(const std::string &subdir)
Set the subdirectory.
 
void invalidate()
Invalidate this instance.
 
std::chrono::sys_days m_sysday
System time representation of the date of this sub directory.
 
unsigned int month(mx::error_t *errc=nullptr) const
Get the current value of m_month.
 
stdSubDir followingSubdir(mx::error_t *errc=nullptr)
Get the following day's subdirectory.
 
bool valid() const
Get the current value of m_valid.
 
int year(mx::error_t *errc=nullptr) const
Get the current value of m_year.
 
stdSubDir(const std::chrono::sys_days &sysday)
Construct from std::sys_days.
 
bool operator>=(const stdSubDir &comp) const
Compare two subdirectories for greater-than-or-equal by timestamp.
 
stdSubDir()
Default c'tor.
 
mx::error_t subDay()
Subtract a day from this subdirectory.
 
bool operator!=(const stdSubDir &comp) const
Compare two subdirectories for inequality by timestamp.
 
bool operator==(const stdSubDir &comp) const
Compare two subdirectories for equality by timestamp.
 
stdSubDir previousSubdir(mx::error_t *errc=nullptr)
Get the previous day's subdirectory.
 
bool operator>(const stdSubDir &comp) const
Compare two subdirectories for greater-than by timestamp.
 
stdSubDir(const std::string &subdir)
Construct from a string.
 
mx::error_t addDay()
Add a day to this subdirectory.
 
std::string path(mx::error_t *errc=nullptr) const
Get the current value of m_subDir.
 
bool operator<=(const stdSubDir &comp) const
Compare two subdirectories for less-than-or-equal by timestamp.
 
Augments an exception with the source file and line.
 
#define XWCTEST_NAMESPACE