Line data Source code
1 : /** \file stdSubDir.hpp
2 : * \brief The stdSubDir class for managing subdirectories
3 : *
4 : * \ingroup file_files
5 : *
6 : */
7 :
8 : #ifndef file_stdSubDir_hpp
9 : #define file_stdSubDir_hpp
10 :
11 : #include <string>
12 : #include <chrono>
13 :
14 : #include <mx/mxlib.hpp>
15 : #include <mx/ioutils/stringUtils.hpp>
16 : #include "../common/exceptions.hpp"
17 :
18 : #include "../common/defaults.hpp"
19 :
20 : namespace MagAOX
21 : {
22 : namespace file
23 : {
24 :
25 : #ifdef XWCTEST_NAMESPACE
26 : namespace XWCTEST_NAMESPACE
27 : {
28 : #endif
29 :
30 : /// Manage a standard subdirectory
31 : /** MagAO-X data storage subdirectories have the format YYYY_MM_DD
32 : * This class provides parsing and date arithmetic.
33 : */
34 : template <typename verboseT = XWC_DEFAULT_VERBOSITY>
35 : class stdSubDir
36 : {
37 :
38 : protected:
39 : std::chrono::sys_days m_sysday; ///< System time representation of the date of this sub directory
40 :
41 : mutable bool m_pathMade{ false }; ///< Whether or not the path string has been constructed
42 :
43 : mutable std::string m_path; ///< The path string. Only constructed on demand.
44 :
45 : bool m_valid{ false }; ///< Whether or not the components are valid
46 :
47 : public:
48 : /// Default c'tor
49 : stdSubDir();
50 :
51 : /// Construct from std::sys_days
52 : /**
53 : * On success, sets `m_valid=true`
54 : *
55 : * On error, sets `m_valid=false`
56 : */
57 : explicit stdSubDir( const std::chrono::sys_days &sysday /**< [in] The new year*/ );
58 :
59 : /// Construct from components
60 : /**
61 : * On success, sets `m_valid=true`
62 : *
63 : * On error, sets `m_valid=false`
64 : */
65 : stdSubDir( int year, /**< [in] The new year*/
66 : unsigned month, /**< [in] The new month*/
67 : unsigned day /**< [in] The new day*/
68 : );
69 :
70 : /// Construct from a string
71 : /**
72 : * On success, sets `m_valid=true`
73 : *
74 : * On error, sets `m_valid=false`
75 : */
76 : stdSubDir( const std::string &subdir /**< [in] The string of format YYYY_MM_DD*/ );
77 :
78 : /// Setup from components
79 : /**
80 : * On success, sets `m_valid=true`
81 : *
82 : * On error, sets `m_valid=false`
83 : */
84 : mx::error_t ymd( int year, /**< [in] The new year*/
85 : unsigned month, /**< [in] The new month*/
86 : unsigned day /**< [in] The new day*/
87 : );
88 :
89 : /// Set the subdirectory
90 : /**
91 : * Parses the string and sets the time point
92 : */
93 : mx::error_t path( const std::string &subdir );
94 :
95 : /// Get the current value of m_subDir
96 : /**
97 : * \returns the current value of m_subDir if valid and path construction succeeds
98 : * \returns empty string "" if invalid or path construction fails
99 : */
100 : std::string path( mx::error_t *errc = nullptr /**< [in] [optional] error code set during path creation */ ) const;
101 :
102 : /// Get the current value of m_year
103 : /**
104 : * \returns the current value of m_year if valid
105 : * \returns std::numeric_limits<int>::max() if invalid
106 : */
107 : int year( mx::error_t *errc = nullptr /**< [in] [optional] error code set during path creation */ ) const;
108 :
109 : /// Get the current value of m_month
110 : /**
111 : * \returns the current value of m_month if valid
112 : * \returns std::numeric_limits<unsigned int>::max() if invalid
113 : */
114 : unsigned int month( mx::error_t *errc = nullptr /**< [in] [optional] error code set during path creation */ ) const;
115 :
116 : /// Get the current value of m_day
117 : /**
118 : * \returns the current value of m_day if valid
119 : * \returns std::numeric_limits<unsigned int>::max() if invalid
120 : */
121 : unsigned int day( mx::error_t *errc = nullptr /**< [in] [optional] error code set during path creation */ ) const;
122 :
123 : /// Get the current value of m_valid
124 : /**
125 : * \returns the current value of m_valid
126 : */
127 : bool valid() const;
128 :
129 : // Manipulations
130 :
131 : /// Add a day to this subdirectory
132 : mx::error_t addDay();
133 :
134 : /// Subtract a day from this subdirectory
135 : mx::error_t subDay();
136 :
137 : /// Get the previous day's subdirectory
138 : stdSubDir previousSubdir( mx::error_t *errc = nullptr /**< [in] [optional] error code set during path creation */ );
139 :
140 : /// Get the following day's subdirectory
141 : stdSubDir followingSubdir( mx::error_t *errc = nullptr /**< [in] [optional] error code set during path creation */
142 : );
143 :
144 : /// Compare two subdirectories for equality by timestamp
145 : /** Two subdirectories are equal if and only if their timestamps are equal
146 : *
147 : */
148 : bool operator==( const stdSubDir &comp ) const;
149 :
150 : /// Compare two subdirectories for inequality by timestamp
151 : /** Two subdirectories are equal if and only if their timestamps are equal
152 : *
153 : */
154 : bool operator!=( const stdSubDir &comp ) const;
155 :
156 : /// Compare two subdirectories for less-than by timestamp
157 : /** A subdirectory is less than if and only if its timestamp is less-than
158 : *
159 : */
160 : bool operator<( const stdSubDir &comp ) const;
161 :
162 : /// Compare two subdirectories for less-than-or-equal by timestamp
163 : /** A subdirectory is less than or equal if and only if its timestamp is less-than-or-equal
164 : *
165 : */
166 : bool operator<=( const stdSubDir &comp ) const;
167 :
168 : /// Compare two subdirectories for greater-than by timestamp
169 : /** A subdirectory is greater than if and only if its timestamp is greater-than
170 : *
171 : */
172 : bool operator>( const stdSubDir &comp ) const;
173 :
174 : /// Compare two subdirectories for greater-than-or-equal by timestamp
175 : /** A subdirectory is greater than if and only if its timestamp is greater-than-or-equal
176 : *
177 : */
178 : bool operator>=( const stdSubDir &comp ) const;
179 :
180 : /// Invalidate this instance
181 : void invalidate();
182 :
183 : };
184 :
185 : template <typename verboseT>
186 146 : stdSubDir<verboseT>::stdSubDir()
187 : {
188 146 : return;
189 : }
190 :
191 : template <typename verboseT>
192 3 : stdSubDir<verboseT>::stdSubDir( const std::chrono::sys_days &sysday )
193 : {
194 : try
195 : {
196 : // clang-format off
197 : #ifdef XWCTEST_STDSUBDIR_CTORSYSDAYS_BAD_ALLOC
198 : throw std::bad_alloc(); // LCOV_EXCL_LINE
199 : #endif
200 :
201 : #ifdef XWCTEST_STDSUBDIR_CTORSYSDAYS_EXCEPTION
202 : throw std::exception(); // LCOV_EXCL_LINE
203 : #endif
204 : // clang-format on
205 :
206 1 : m_sysday = sysday;
207 1 : m_valid = true;
208 : }
209 3 : catch( const std::bad_alloc &e )
210 : {
211 4 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
212 : }
213 2 : catch( const std::exception &e )
214 : {
215 3 : mx::error_report<verboseT>( mx::error_t::std_exception, std::string( "chrono operations: " ) + e.what() );
216 : }
217 3 : }
218 :
219 : template <typename verboseT>
220 58 : stdSubDir<verboseT>::stdSubDir( int year, unsigned month, unsigned day )
221 : {
222 58 : ymd( year, month, day );
223 58 : }
224 :
225 : template <typename verboseT>
226 20 : stdSubDir<verboseT>::stdSubDir( const std::string &subdir )
227 : {
228 20 : path( subdir );
229 20 : }
230 :
231 : template <typename verboseT>
232 145 : mx::error_t stdSubDir<verboseT>::ymd( int year, unsigned month, unsigned day )
233 : {
234 : // we technically could be subtle about this and wait for changes to occur
235 : // but we'll just propagate any errors as invalidating this instance
236 145 : invalidate();
237 :
238 : try
239 : {
240 : // clang-format off
241 : #ifdef XWCTEST_STDSUBDIR_YMD_BAD_ALLOC
242 : throw std::bad_alloc(); // LCOV_EXCL_LINE
243 : #endif
244 :
245 : #ifdef XWCTEST_STDSUBDIR_YMD_EXCEPTION
246 : throw std::exception(); // LCOV_EXCL_LINE
247 : #endif
248 : // clang-format on
249 :
250 141 : std::chrono::year_month_day ymd{
251 141 : std::chrono::year( year ), std::chrono::month( month ), std::chrono::day( day ) };
252 :
253 141 : m_sysday = ymd;
254 :
255 141 : m_valid = true;
256 141 : return mx::error_t::noerror;
257 : }
258 6 : catch( const std::bad_alloc &e )
259 : {
260 8 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
261 : }
262 4 : catch( const std::exception &e )
263 : {
264 4 : return mx::error_report<verboseT>( mx::error_t::std_exception,
265 10 : std::string( "chrono operations: " ) + e.what() );
266 : }
267 : }
268 :
269 : template <typename verboseT>
270 39 : mx::error_t stdSubDir<verboseT>::path( const std::string &subdir )
271 : {
272 : // we technically could be subtle about this and wait for changes to occur
273 : // but we'll just propagate any errors as invalidating this instance
274 39 : invalidate();
275 :
276 39 : if( subdir.length() != 10 )
277 : {
278 3 : return mx::error_report<verboseT>( mx::error_t::invalidarg, "subdir " + subdir + " is not 10 chars long " );
279 : }
280 :
281 105 : for( size_t n : { 4, 7 } )
282 : {
283 71 : if( subdir[n] != '_' )
284 : {
285 2 : return mx::error_report<verboseT>( mx::error_t::invalidarg, "subdir " + subdir + " is missing _ " );
286 : }
287 : }
288 :
289 270 : for( size_t n : { 0, 1, 2, 3, 5, 6, 8, 9 } )
290 : {
291 244 : if( !isdigit( subdir[n] ) )
292 : {
293 16 : return mx::error_report<verboseT>( mx::error_t::invalidarg,
294 8 : "subdir " + subdir + " has non-digit at " + std::to_string( n ) );
295 : }
296 : }
297 :
298 : mx::error_t errc;
299 :
300 : int year;
301 : unsigned int month, day;
302 :
303 : try
304 : {
305 : // clang-format off
306 : #ifdef XWCTEST_STDSUBDIR_SETPATH_BAD_ALLOC
307 : throw std::bad_alloc(); // LCOV_EXCL_LINE
308 : #endif
309 :
310 : #ifdef XWCTEST_STDSUBDIR_SETPATH_OUT_OF_RANGE
311 : throw std::out_of_range("test"); // LCOV_EXCL_LINE
312 : #endif
313 :
314 : #ifdef XWCTEST_STDSUBDIR_SETPATH_EXCEPTION
315 : throw std::exception(); // LCOV_EXCL_LINE
316 : #endif
317 : // clang-format on
318 :
319 20 : year = mx::ioutils::stoT<int>( subdir.substr( 0, 4 ), errc );
320 20 : mx_error_check_code( errc );
321 :
322 20 : month = mx::ioutils::stoT<unsigned int>( subdir.substr( 5, 2 ), errc );
323 20 : mx_error_check_code( errc );
324 :
325 20 : day = mx::ioutils::stoT<unsigned int>( subdir.substr( 8, 2 ), errc );
326 20 : mx_error_check_code( errc );
327 : }
328 8 : catch( const std::bad_alloc &e )
329 : {
330 8 : std::throw_with_nested( xwcException( "parsing subdir", -6 ) );
331 : }
332 4 : catch( const std::out_of_range &e )
333 : {
334 6 : return mx::error_report<verboseT>( mx::error_t::std_out_of_range, std::string( "parsing subdir" ) + e.what() );
335 : }
336 4 : catch( const std::exception &e )
337 : {
338 6 : return mx::error_report<verboseT>( mx::error_t::std_exception, std::string( "parsing subdir" ) + e.what() );
339 : }
340 :
341 : try
342 : {
343 : // clang-format off
344 : #ifdef XWCTEST_STDSUBDIR_SETPATH_BAD_ALLOC2
345 : throw std::bad_alloc(); // LCOV_EXCL_LINE
346 : #endif
347 :
348 : #ifdef XWCTEST_STDSUBDIR_SETPATH_EXCEPTION2
349 : throw std::exception(); // LCOV_EXCL_LINE
350 : #endif
351 : // clang-format on
352 :
353 16 : std::chrono::year_month_day ymd{
354 16 : std::chrono::year( year ), std::chrono::month( month ), std::chrono::day( day ) };
355 :
356 16 : m_sysday = ymd;
357 :
358 16 : m_path = subdir;
359 16 : m_pathMade = true;
360 :
361 16 : m_valid = true;
362 :
363 16 : return mx::error_t::noerror;
364 : }
365 6 : catch( const std::bad_alloc &e )
366 : {
367 8 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
368 : }
369 4 : catch( const std::exception &e )
370 : {
371 4 : return mx::error_report<verboseT>( mx::error_t::std_exception,
372 10 : std::string( "chrono operations: " ) + e.what() );
373 : }
374 : }
375 :
376 : template <typename verboseT>
377 475 : std::string stdSubDir<verboseT>::path( mx::error_t *errc ) const
378 : {
379 475 : if( !m_valid )
380 : {
381 4 : if( errc )
382 : {
383 2 : *errc = mx::error_t::invalidconfig;
384 : }
385 8 : mx::error_report<verboseT>( mx::error_t::invalidconfig, "attempt to access path while invalid" );
386 8 : return "";
387 : }
388 :
389 471 : if( !m_pathMade )
390 : {
391 : try
392 : {
393 : // clang-format off
394 : #ifdef XWCTEST_STDSUBDIR_MAKEPATH_BAD_ALLOC
395 : throw std::bad_alloc(); // LCOV_EXCL_LINE
396 : #endif
397 :
398 : #ifdef XWCTEST_STDSUBDIR_MAKEPATH_FORMAT_ERROR
399 : throw std::format_error("test"); // LCOV_EXCL_LINE
400 : #endif
401 :
402 : #ifdef XWCTEST_STDSUBDIR_MAKEPATH_EXCEPTION
403 : throw std::exception(); // LCOV_EXCL_LINE
404 : #endif
405 : // clang-format on
406 :
407 445 : m_path = std::format( "{:%Y_%m_%d}", m_sysday );
408 :
409 445 : m_pathMade = true;
410 : }
411 4 : catch( const std::bad_alloc &e )
412 : {
413 4 : std::throw_with_nested( xwcException( "bad_alloc from std::format", -12 ) );
414 : }
415 1 : catch( const std::format_error &e )
416 : {
417 1 : if( errc )
418 : {
419 1 : *errc = mx::error_t::std_format_error;
420 : }
421 3 : mx::error_report<verboseT>( mx::error_t::std_format_error, std::string( "from std::format: " ) + e.what() );
422 2 : return "";
423 : }
424 1 : catch( const std::exception &e )
425 : {
426 1 : if( errc )
427 : {
428 1 : *errc = mx::error_t::std_exception;
429 : }
430 3 : mx::error_report<verboseT>( mx::error_t::std_exception, std::string( "from std::format: " ) + e.what() );
431 2 : return "";
432 : }
433 : }
434 :
435 468 : if( errc )
436 : {
437 1 : *errc = mx::error_t::noerror;
438 : }
439 468 : return m_path;
440 : }
441 :
442 : template <typename verboseT>
443 36 : int stdSubDir<verboseT>::year( mx::error_t *errc ) const
444 : {
445 36 : if( !m_valid )
446 : {
447 3 : if( errc )
448 : {
449 2 : *errc = mx::error_t::invalidconfig;
450 : }
451 6 : mx::error_report<verboseT>( mx::error_t::invalidconfig, "attempt to access year while invalid" );
452 3 : return std::numeric_limits<int>::max();
453 : }
454 :
455 : try
456 : {
457 : // clang-format off
458 : #ifdef XWCTEST_STDSUBDIR_GYMD_BAD_ALLOC
459 : throw std::bad_alloc(); // LCOV_EXCL_LINE
460 : #endif
461 :
462 : #ifdef XWCTEST_STDSUBDIR_GYMD_EXCEPTION
463 : throw std::exception(); // LCOV_EXCL_LINE
464 : #endif
465 : // clang-format on
466 :
467 31 : std::chrono::year_month_day ymd{ m_sysday };
468 :
469 31 : if( errc )
470 : {
471 4 : *errc = mx::error_t::noerror;
472 : }
473 :
474 31 : return static_cast<int>( ymd.year() );
475 : }
476 3 : catch( const std::bad_alloc &e )
477 : {
478 1 : if( errc )
479 : {
480 1 : *errc = mx::error_t::std_bad_alloc;
481 : }
482 4 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
483 : }
484 2 : catch( const std::exception &e )
485 : {
486 1 : if( errc )
487 : {
488 1 : *errc = mx::error_t::std_exception;
489 : }
490 3 : mx::error_report<verboseT>( mx::error_t::std_exception, std::string( "chrono operations: " ) + e.what() );
491 1 : return std::numeric_limits<int>::max();
492 : }
493 : }
494 :
495 : template <typename verboseT>
496 36 : unsigned int stdSubDir<verboseT>::month( mx::error_t *errc ) const
497 : {
498 36 : if( !m_valid )
499 : {
500 3 : if( errc )
501 : {
502 2 : *errc = mx::error_t::invalidconfig;
503 : }
504 6 : mx::error_report<verboseT>( mx::error_t::invalidconfig, "attempt to access month while invalid" );
505 3 : return std::numeric_limits<unsigned int>::max();
506 : }
507 :
508 : try
509 : {
510 : // clang-format off
511 : #ifdef XWCTEST_STDSUBDIR_GYMD_BAD_ALLOC
512 : throw std::bad_alloc(); // LCOV_EXCL_LINE
513 : #endif
514 :
515 : #ifdef XWCTEST_STDSUBDIR_GYMD_EXCEPTION
516 : throw std::exception(); // LCOV_EXCL_LINE
517 : #endif
518 : // clang-format on
519 :
520 31 : std::chrono::year_month_day ymd{ m_sysday };
521 :
522 31 : if( errc )
523 : {
524 4 : *errc = mx::error_t::noerror;
525 : }
526 31 : return static_cast<unsigned>( ymd.month() );
527 : }
528 3 : catch( const std::bad_alloc &e )
529 : {
530 1 : if( errc )
531 : {
532 1 : *errc = mx::error_t::std_bad_alloc;
533 : }
534 4 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
535 : }
536 2 : catch( const std::exception &e )
537 : {
538 1 : if( errc )
539 : {
540 1 : *errc = mx::error_t::std_exception;
541 : }
542 3 : mx::error_report<verboseT>( mx::error_t::std_exception, std::string( "chrono operations: " ) + e.what() );
543 1 : return std::numeric_limits<unsigned int>::max();
544 : }
545 : }
546 :
547 : template <typename verboseT>
548 36 : unsigned int stdSubDir<verboseT>::day( mx::error_t *errc ) const
549 : {
550 36 : if( !m_valid )
551 : {
552 3 : if( errc )
553 : {
554 2 : *errc = mx::error_t::invalidconfig;
555 : }
556 6 : mx::error_report<verboseT>( mx::error_t::invalidconfig, "attempt to access day while invalid" );
557 3 : return std::numeric_limits<unsigned int>::max();
558 : }
559 :
560 : try
561 : {
562 : // clang-format off
563 : #ifdef XWCTEST_STDSUBDIR_GYMD_BAD_ALLOC
564 : throw std::bad_alloc(); // LCOV_EXCL_LINE
565 : #endif
566 :
567 : #ifdef XWCTEST_STDSUBDIR_GYMD_EXCEPTION
568 : throw std::exception(); // LCOV_EXCL_LINE
569 : #endif
570 : // clang-format on
571 :
572 31 : std::chrono::year_month_day ymd{ m_sysday };
573 :
574 31 : if( errc )
575 : {
576 4 : *errc = mx::error_t::noerror;
577 : }
578 31 : return static_cast<unsigned>( ymd.day() );
579 : }
580 3 : catch( const std::bad_alloc &e )
581 : {
582 1 : if( errc )
583 : {
584 1 : *errc = mx::error_t::std_bad_alloc;
585 : }
586 4 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
587 : }
588 2 : catch( const std::exception &e )
589 : {
590 1 : if( errc )
591 : {
592 1 : *errc = mx::error_t::std_exception;
593 : }
594 3 : mx::error_report<verboseT>( mx::error_t::std_exception, std::string( "chrono operations: " ) + e.what() );
595 1 : return std::numeric_limits<unsigned int>::max();
596 : }
597 : }
598 :
599 : template <typename verboseT>
600 103 : bool stdSubDir<verboseT>::valid() const
601 : {
602 103 : return m_valid;
603 : }
604 :
605 : template <typename verboseT>
606 122 : mx::error_t stdSubDir<verboseT>::addDay()
607 : {
608 122 : if( !m_valid )
609 : {
610 2 : return mx::error_report<verboseT>( mx::error_t::invalidconfig, "attempt to access while invalid" );
611 : }
612 :
613 : try
614 : {
615 : // clang-format off
616 : #ifdef XWCTEST_STDSUBDIR_INC_BAD_ALLOC
617 : throw std::bad_alloc(); // LCOV_EXCL_LINE
618 : #endif
619 :
620 : #ifdef XWCTEST_STDSUBDIR_INC_EXCEPTION
621 : throw std::exception(); // LCOV_EXCL_LINE
622 : #endif
623 : // clang-format on
624 :
625 117 : m_pathMade = false;
626 117 : ++m_sysday;
627 : }
628 6 : catch( const std::bad_alloc &e )
629 : {
630 2 : invalidate();
631 8 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
632 : }
633 4 : catch( const std::exception &e )
634 : {
635 2 : invalidate();
636 4 : return mx::error_report<verboseT>( mx::error_t::std_exception,
637 10 : std::string( "chrono operations: " ) + e.what() );
638 : }
639 :
640 117 : return mx::error_t::noerror;
641 : }
642 :
643 : template <typename verboseT>
644 315 : mx::error_t stdSubDir<verboseT>::subDay()
645 : {
646 315 : if( !m_valid )
647 : {
648 2 : return mx::error_report<verboseT>( mx::error_t::invalidconfig, "attempt to access while invalid" );
649 : }
650 :
651 : try
652 : {
653 : // clang-format off
654 : #ifdef XWCTEST_STDSUBDIR_INC_BAD_ALLOC
655 : throw std::bad_alloc(); // LCOV_EXCL_LINE
656 : #endif
657 :
658 : #ifdef XWCTEST_STDSUBDIR_INC_EXCEPTION
659 : throw std::exception(); // LCOV_EXCL_LINE
660 : #endif
661 : // clang-format on
662 :
663 310 : --m_sysday;
664 :
665 310 : m_pathMade = false;
666 :
667 310 : return mx::error_t::noerror;
668 : }
669 6 : catch( const std::bad_alloc &e )
670 : {
671 2 : invalidate();
672 8 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
673 : }
674 4 : catch( const std::exception &e )
675 : {
676 2 : invalidate();
677 4 : return mx::error_report<verboseT>( mx::error_t::std_exception,
678 10 : std::string( "chrono operations: " ) + e.what() );
679 : }
680 : }
681 :
682 : template <typename verboseT>
683 10 : stdSubDir<verboseT> stdSubDir<verboseT>::previousSubdir( mx::error_t *errc )
684 : {
685 10 : if( !m_valid )
686 : {
687 1 : if( errc )
688 : {
689 1 : *errc = mx::error_t::invalidconfig;
690 : }
691 2 : mx::error_report<verboseT>( mx::error_t::invalidconfig, "attempt to access while invalid" );
692 1 : return stdSubDir();
693 : }
694 :
695 : try
696 : {
697 : // clang-format off
698 : #ifdef XWCTEST_STDSUBDIR_PREVFOLL_BAD_ALLOC
699 : throw std::bad_alloc(); // LCOV_EXCL_LINE
700 : #endif
701 : // clang-format on
702 :
703 8 : stdSubDir std = *this;
704 :
705 : // clang-format off
706 : #ifdef XWCTEST_STDSUBDIR_PREV_INVAL
707 : // invalidate
708 : std.path(""); // LCOV_EXCL_LINE
709 : #endif
710 : // clang-format on
711 :
712 8 : if( !std.valid() )
713 : {
714 1 : if( errc )
715 : {
716 1 : *errc = mx::error_t::error;
717 : }
718 2 : mx::error_report<verboseT>( mx::error_t::error, "an error occurred creating new subdir" );
719 1 : return stdSubDir();
720 : }
721 :
722 7 : mx::error_t _errc = std.subDay();
723 :
724 6 : if( _errc != mx::error_t::noerror )
725 : {
726 2 : mx::error_report<verboseT>( _errc, "from subDay" );
727 : }
728 :
729 6 : if( errc )
730 : {
731 1 : *errc = _errc;
732 : }
733 :
734 6 : return std;
735 8 : }
736 3 : catch( const std::bad_alloc &e )
737 : {
738 1 : if( errc )
739 : {
740 1 : *errc = mx::error_t::std_bad_alloc;
741 : }
742 4 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
743 : }
744 2 : catch( const xwcException &e )
745 : {
746 1 : if( errc )
747 : {
748 1 : *errc = mx::error_t::std_exception;
749 : }
750 4 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
751 : }
752 : }
753 :
754 : template <typename verboseT>
755 9 : stdSubDir<verboseT> stdSubDir<verboseT>::followingSubdir( mx::error_t *errc )
756 : {
757 9 : if( !m_valid )
758 : {
759 1 : if( errc )
760 : {
761 1 : *errc = mx::error_t::invalidconfig;
762 : }
763 2 : mx::error_report<verboseT>( mx::error_t::invalidconfig, "attempt to access while invalid" );
764 1 : return stdSubDir();
765 : }
766 :
767 : try
768 : {
769 : // clang-format off
770 : #ifdef XWCTEST_STDSUBDIR_PREVFOLL_BAD_ALLOC
771 : throw std::bad_alloc(); // LCOV_EXCL_LINE
772 : #endif
773 : // clang-format on
774 :
775 7 : stdSubDir std = *this;
776 :
777 : // clang-format off
778 : #ifdef XWCTEST_STDSUBDIR_PREV_INVAL
779 : // invalidate
780 : std.path(""); // LCOV_EXCL_LINE
781 : #endif
782 : // clang-format on
783 :
784 7 : if( !std.valid() )
785 : {
786 1 : if( errc )
787 : {
788 1 : *errc = mx::error_t::error;
789 : }
790 2 : mx::error_report<verboseT>( mx::error_t::error, "an error occurred creating new subdir" );
791 1 : return stdSubDir();
792 : }
793 :
794 6 : mx::error_t _errc = std.addDay();
795 :
796 5 : if( _errc != mx::error_t::noerror )
797 : {
798 2 : mx::error_report<verboseT>( _errc, "from subDay" );
799 : }
800 :
801 5 : if( errc )
802 : {
803 1 : *errc = _errc;
804 : }
805 :
806 5 : return std;
807 7 : }
808 3 : catch( const std::bad_alloc &e )
809 : {
810 1 : if( errc )
811 : {
812 1 : *errc = mx::error_t::std_bad_alloc;
813 : }
814 4 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
815 : }
816 2 : catch( const xwcException &e )
817 : {
818 1 : if( errc )
819 : {
820 1 : *errc = mx::error_t::std_exception;
821 : }
822 4 : std::throw_with_nested( xwcException( "chrono operations", -6 ) );
823 : }
824 : }
825 :
826 : template <typename verboseT>
827 7 : bool stdSubDir<verboseT>::operator==( const stdSubDir &comp ) const
828 : {
829 7 : return ( m_sysday == comp.m_sysday );
830 : }
831 :
832 : template <typename verboseT>
833 2 : bool stdSubDir<verboseT>::operator!=( const stdSubDir &comp ) const
834 : {
835 2 : return ( m_sysday != comp.m_sysday );
836 : }
837 :
838 : template <typename verboseT>
839 11 : bool stdSubDir<verboseT>::operator<( const stdSubDir &comp ) const
840 : {
841 11 : return ( m_sysday < comp.m_sysday );
842 : }
843 :
844 : template <typename verboseT>
845 3 : bool stdSubDir<verboseT>::operator<=( const stdSubDir &comp ) const
846 : {
847 3 : return ( m_sysday <= comp.m_sysday );
848 : }
849 :
850 : template <typename verboseT>
851 3 : bool stdSubDir<verboseT>::operator>( const stdSubDir &comp ) const
852 : {
853 3 : return ( m_sysday > comp.m_sysday );
854 : }
855 :
856 : template <typename verboseT>
857 3 : bool stdSubDir<verboseT>::operator>=( const stdSubDir &comp ) const
858 : {
859 3 : return ( m_sysday >= comp.m_sysday );
860 : }
861 :
862 : template <typename verboseT>
863 299 : void stdSubDir<verboseT>::invalidate()
864 : {
865 299 : m_path.clear();
866 :
867 299 : m_pathMade = false;
868 299 : m_valid = false;
869 299 : }
870 :
871 : #ifndef XWCTEST_NAMESPACE
872 : extern template class stdSubDir<XWC_DEFAULT_VERBOSITY>;
873 : #endif
874 :
875 : #ifdef XWCTEST_NAMESPACE
876 : }
877 : #endif
878 :
879 : } // namespace file
880 : } // namespace MagAOX
881 :
882 : #endif // file_stdSubDir_hpp
|