diff options
Diffstat (limited to 'source/core')
-rw-r--r-- | source/core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/core/StarAudio.cpp | 6 | ||||
-rw-r--r-- | source/core/StarException.hpp | 38 | ||||
-rw-r--r-- | source/core/StarException_windows.cpp | 1 | ||||
-rw-r--r-- | source/core/StarFormat.hpp | 79 | ||||
-rw-r--r-- | source/core/StarOutputProxy.hpp | 68 |
6 files changed, 104 insertions, 89 deletions
diff --git a/source/core/CMakeLists.txt b/source/core/CMakeLists.txt index 5e4f090..cf64c3a 100644 --- a/source/core/CMakeLists.txt +++ b/source/core/CMakeLists.txt @@ -83,6 +83,7 @@ SET (star_core_HEADERS StarOptionParser.hpp StarOrderedMap.hpp StarOrderedSet.hpp + StarOutputProxy.hpp StarParametricFunction.hpp StarPch.hpp StarPeriodic.hpp diff --git a/source/core/StarAudio.cpp b/source/core/StarAudio.cpp index ef5d2f4..1718aa8 100644 --- a/source/core/StarAudio.cpp +++ b/source/core/StarAudio.cpp @@ -65,7 +65,7 @@ namespace { if ((strcmp(riffSig.get(), "RIFF") != 0) || (strcmp(waveSig.get(), "WAVE") != 0)) { // bytes are not magic auto p = [](char a) { return isprint(a) ? a : '?'; }; - throw AudioException(strf("Wav file has wrong magic bytes, got `{}{}{}{}' and `{}{}{}{}' but expected `RIFF' and `WAVE'", + throw AudioException(strf("Wav file has wrong magic bytes, got `{:c}{:c}{:c}{:c}' and `{:c}{:c}{:c}{:c}' but expected `RIFF' and `WAVE'", p(riffSig[0]), p(riffSig[1]), p(riffSig[2]), p(riffSig[3]), p(waveSig[0]), p(waveSig[1]), p(waveSig[2]), p(waveSig[3]))); } @@ -74,7 +74,7 @@ namespace { device->readFull(fmtSig.get(), sigLength); if (strcmp(fmtSig.get(), "fmt ") != 0) { // friendship is magic auto p = [](char a) { return isprint(a) ? a : '?'; }; - throw AudioException(strf("Wav file fmt subchunk has wrong magic bytes, got `{}{}{}{}' but expected `fmt '", + throw AudioException(strf("Wav file fmt subchunk has wrong magic bytes, got `{:c}{:c}{:c}{:c}' but expected `fmt '", p(fmtSig[0]), p(fmtSig[1]), p(fmtSig[2]), @@ -110,7 +110,7 @@ namespace { device->readFull(dataSig.get(), sigLength); if (strcmp(dataSig.get(), "data") != 0) { // magic or more magic? auto p = [](char a) { return isprint(a) ? a : '?'; }; - throw AudioException(strf("Wav file data subchunk has wrong magic bytes, got `{}{}{}{}' but expected `data'", + throw AudioException(strf("Wav file data subchunk has wrong magic bytes, got `{:c}{:c}{:c}{:c}' but expected `data'", p(dataSig[0]), p(dataSig[1]), p(dataSig[2]), p(dataSig[3]))); } diff --git a/source/core/StarException.hpp b/source/core/StarException.hpp index 4774dd2..0e6a4ed 100644 --- a/source/core/StarException.hpp +++ b/source/core/StarException.hpp @@ -1,10 +1,18 @@ #ifndef STAR_EXCEPTION_HPP #define STAR_EXCEPTION_HPP -#include "StarFormat.hpp" +#include "StarMemory.hpp" +#include "StarOutputProxy.hpp" + + +#include <string> + namespace Star { +template <typename... T> +std::string strf(fmt::format_string<T...> fmt, T&&... args); + class StarException : public std::exception { public: template <typename... Args> @@ -68,22 +76,22 @@ void fatalException(std::exception const& e, bool showStackTrace); {} #endif -#define STAR_EXCEPTION(ClassName, BaseName) \ - class ClassName : public BaseName { \ - public: \ - template <typename... Args> \ - static ClassName format(fmt::format_string<Args...> fmt, Args const&... args) { \ - return ClassName(strf(fmt, args...)); \ - } \ - ClassName() : BaseName(#ClassName, std::string()) {} \ +#define STAR_EXCEPTION(ClassName, BaseName) \ + class ClassName : public BaseName { \ + public: \ + template <typename... Args> \ + static ClassName format(fmt::format_string<Args...> fmt, Args const&... args) { \ + return ClassName(strf(fmt, args...)); \ + } \ + ClassName() : BaseName(#ClassName, std::string()) {} \ explicit ClassName(std::string message, bool genStackTrace = true) : BaseName(#ClassName, move(message), genStackTrace) {} \ - explicit ClassName(std::exception const& cause) : BaseName(#ClassName, std::string(), cause) {} \ - ClassName(std::string message, std::exception const& cause) : BaseName(#ClassName, move(message), cause) {} \ - \ - protected: \ + explicit ClassName(std::exception const& cause) : BaseName(#ClassName, std::string(), cause) {} \ + ClassName(std::string message, std::exception const& cause) : BaseName(#ClassName, move(message), cause) {} \ + \ + protected: \ ClassName(char const* type, std::string message, bool genStackTrace = true) : BaseName(type, move(message), genStackTrace) {} \ - ClassName(char const* type, std::string message, std::exception const& cause) \ - : BaseName(type, move(message), cause) {} \ + ClassName(char const* type, std::string message, std::exception const& cause) \ + : BaseName(type, move(message), cause) {} \ } STAR_EXCEPTION(OutOfRangeException, StarException); diff --git a/source/core/StarException_windows.cpp b/source/core/StarException_windows.cpp index 87d9ed6..8f5786f 100644 --- a/source/core/StarException_windows.cpp +++ b/source/core/StarException_windows.cpp @@ -1,4 +1,5 @@ #include "StarException.hpp" +#include "StarOutputProxy.hpp" #include "StarLogging.hpp" #include "StarCasting.hpp" #include "StarString_windows.hpp" diff --git a/source/core/StarFormat.hpp b/source/core/StarFormat.hpp index ccfb80c..c31697f 100644 --- a/source/core/StarFormat.hpp +++ b/source/core/StarFormat.hpp @@ -2,6 +2,7 @@ #define STAR_FORMAT_HPP #include "StarMemory.hpp" +#include "StarException.hpp" #include "fmt/core.h" #include "fmt/ostream.h" @@ -10,23 +11,19 @@ namespace Star { -struct FormatException : public std::exception { - FormatException(std::string what) : whatmsg(move(what)) {} +STAR_EXCEPTION(FormatException, StarException); - char const* what() const noexcept override { - return whatmsg.c_str(); +template <typename... T> +std::string strf(fmt::format_string<T...> fmt, T&&... args) { + try { return fmt::format(fmt, args...); } + catch (std::exception const& e) { + throw FormatException(strf("Exception thrown during string format: {}", e.what())); } - - std::string whatmsg; -}; - } -namespace Star { - template <typename... T> void format(std::ostream& out, fmt::format_string<T...> fmt, T&&... args) { - out << fmt::format(fmt, args...); + out << strf(fmt, args...); } // Automatically flushes, use format to avoid flushing. @@ -43,66 +40,6 @@ void cerrf(char const* fmt, Args const&... args) { std::cerr.flush(); } -template <typename... T> -std::string strf(fmt::format_string<T...> fmt, T&&... args) { - return fmt::format(fmt, args...); -} - -namespace OutputAnyDetail { - template<typename T, typename CharT, typename Traits> - std::basic_string<CharT, Traits> string(T const& t) { - return fmt::format("<type {} at address: {}>", typeid(T).name(), (void*)&t); - } - - template<typename T, typename CharT, typename Traits> - std::basic_ostream<CharT, Traits>& output(std::basic_ostream<CharT, Traits>& os, T const& t) { - return os << string<T, CharT, Traits>(t); - } - - namespace Operator { - template<typename T, typename CharT, typename Traits> - std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, T const& t) { - return output(os, t); - } - } - - template <typename T> - struct Wrapper { - T const& wrapped; - }; - - template <typename T> - std::ostream& operator<<(std::ostream& os, Wrapper<T> const& wrapper) { - using namespace Operator; - return os << wrapper.wrapped; - } -} - -// Wraps a type so that is printable no matter what.. If no operator<< is -// defined for a type, then will print <type [typeid] at address: [address]> -template <typename T> -OutputAnyDetail::Wrapper<T> outputAny(T const& t) { - return OutputAnyDetail::Wrapper<T>{t}; -} - -struct OutputProxy { - typedef function<void(std::ostream&)> PrintFunction; - - OutputProxy(PrintFunction p) - : print(move(p)) {} - - PrintFunction print; -}; - -inline std::ostream& operator<<(std::ostream& os, OutputProxy const& p) { - p.print(os); - return os; } -} - -template <typename T> -struct fmt::formatter<Star::OutputAnyDetail::Wrapper<T>> : ostream_formatter {}; -template <> struct fmt::formatter<Star::OutputProxy> : ostream_formatter {}; - #endif diff --git a/source/core/StarOutputProxy.hpp b/source/core/StarOutputProxy.hpp new file mode 100644 index 0000000..6449d94 --- /dev/null +++ b/source/core/StarOutputProxy.hpp @@ -0,0 +1,68 @@ +#ifndef STAR_OUTPUT_PROXY_HPP +#define STAR_OUTPUT_PROXY_HPP + +#include "StarMemory.hpp" + +#include "fmt/format.h" +#include "fmt/ostream.h" + +namespace Star { + +namespace OutputAnyDetail { + template<typename T, typename CharT, typename Traits> + std::basic_string<CharT, Traits> string(T const& t) { + return fmt::format("<type {} at address: {}>", typeid(T).name(), (void*)&t); + } + + template<typename T, typename CharT, typename Traits> + std::basic_ostream<CharT, Traits>& output(std::basic_ostream<CharT, Traits>& os, T const& t) { + return os << string<T, CharT, Traits>(t); + } + + namespace Operator { + template<typename T, typename CharT, typename Traits> + std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, T const& t) { + return output(os, t); + } + } + + template <typename T> + struct Wrapper { + T const& wrapped; + }; + + template <typename T> + std::ostream& operator<<(std::ostream& os, Wrapper<T> const& wrapper) { + using namespace Operator; + return os << wrapper.wrapped; + } +} + +// Wraps a type so that is printable no matter what.. If no operator<< is +// defined for a type, then will print <type [typeid] at address: [address]> +template <typename T> +OutputAnyDetail::Wrapper<T> outputAny(T const& t) { + return OutputAnyDetail::Wrapper<T>{t}; +} + +struct OutputProxy { + typedef function<void(std::ostream&)> PrintFunction; + + OutputProxy(PrintFunction p) + : print(move(p)) {} + + PrintFunction print; +}; + +inline std::ostream& operator<<(std::ostream& os, OutputProxy const& p) { + p.print(os); + return os; +} + +} + +template <typename T> +struct fmt::formatter<Star::OutputAnyDetail::Wrapper<T>> : ostream_formatter {}; +template <> struct fmt::formatter<Star::OutputProxy> : ostream_formatter {}; + +#endif
\ No newline at end of file |