|
1 | 1 | #pragma once
|
2 | 2 |
|
3 |
| -#include <string> |
4 |
| -#include <vector> |
| 3 | +#include <algorithm> |
5 | 4 | #include <deque>
|
| 5 | +#include <functional> |
| 6 | +#include <iterator> |
6 | 7 | #include <memory>
|
7 | 8 | #include <mutex>
|
8 | 9 | #include <sstream>
|
9 |
| -#include <algorithm> |
10 |
| -#include <functional> |
| 10 | +#include <string> |
| 11 | +#include <vector> |
| 12 | + |
| 13 | +#ifdef __cpp_lib_print |
| 14 | +# include <print> |
| 15 | +#endif |
11 | 16 |
|
12 | 17 | #include "ffmpeg.h"
|
13 | 18 | #include "avtime.h"
|
@@ -431,5 +436,76 @@ void array_to_container(const T* array, Container &container, Compare isEnd, Cal
|
431 | 436 | container.push_back(convert(value));
|
432 | 437 | }
|
433 | 438 |
|
| 439 | + |
| 440 | +// printing |
| 441 | +#ifdef __cpp_lib_print |
| 442 | +using std::print; |
| 443 | +#else |
| 444 | + |
| 445 | +namespace internal { |
| 446 | +struct fp_output_iterator |
| 447 | +{ |
| 448 | + /// One of the @link iterator_tags tag types@endlink. |
| 449 | + typedef std::output_iterator_tag iterator_category; |
| 450 | + /// The type "pointed to" by the iterator. |
| 451 | + typedef void value_type; |
| 452 | + /// Distance between iterators is represented as this type. |
| 453 | + typedef ptrdiff_t difference_type; |
| 454 | + /// This type represents a pointer-to-value_type. |
| 455 | + typedef void pointer; |
| 456 | + /// This type represents a reference-to-value_type. |
| 457 | + typedef void reference; |
| 458 | + |
| 459 | +private: |
| 460 | + std::FILE *m_fp{nullptr}; |
| 461 | + |
| 462 | +public: |
| 463 | + fp_output_iterator(std::FILE *out) noexcept |
| 464 | + : m_fp(out) |
| 465 | + {} |
| 466 | + |
| 467 | + fp_output_iterator(const fp_output_iterator& obj) noexcept |
| 468 | + : m_fp(obj.m_fp) |
| 469 | + {} |
| 470 | + fp_output_iterator& operator=(const fp_output_iterator&) = default; |
| 471 | + |
| 472 | + fp_output_iterator& operator=(char ch) { |
| 473 | + fputc(ch, m_fp); |
| 474 | + return *this; |
| 475 | + } |
| 476 | + |
| 477 | + fp_output_iterator& operator=(const char *str) { |
| 478 | + fputs(str, m_fp); |
| 479 | + return *this; |
| 480 | + } |
| 481 | + |
| 482 | + [[nodiscard]] fp_output_iterator& operator*() noexcept { return *this; } |
| 483 | + fp_output_iterator& operator++() noexcept { return *this; } |
| 484 | + fp_output_iterator& operator++(int) noexcept { return *this; } |
| 485 | +}; |
| 486 | +} // ::internal |
| 487 | + |
| 488 | +template<class... Args> |
| 489 | +void print(std::FILE* stream, std::format_string<Args...> fmt, Args&&... args) |
| 490 | +{ |
| 491 | + internal::fp_output_iterator out{stream}; |
| 492 | + std::format_to(out, std::move(fmt), std::forward<Args>(args)...); |
| 493 | +} |
| 494 | + |
| 495 | +template<class... Args> |
| 496 | +void print(std::format_string<Args...> fmt, Args&&... args) |
| 497 | +{ |
| 498 | + av::print(stdout, std::move(fmt), std::forward<Args>(args)...); |
| 499 | +} |
| 500 | + |
| 501 | +template<class... Args> |
| 502 | +std::ostream& print(std::ostream &stream, std::format_string<Args...> fmt, Args&&... args) |
| 503 | +{ |
| 504 | + std::ostream_iterator<char> out{stream}; |
| 505 | + std::format_to(out, std::move(fmt), std::forward<Args>(args)...); |
| 506 | + return stream; |
| 507 | +} |
| 508 | +#endif |
| 509 | + |
434 | 510 | } // ::av
|
435 | 511 |
|
0 commit comments