| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- // base/kaldi-error.h
- // Copyright 2019 LAIX (Yi Sun)
- // Copyright 2019 SmartAction LLC (kkm)
- // Copyright 2016 Brno University of Technology (author: Karel Vesely)
- // Copyright 2009-2011 Microsoft Corporation; Ondrej Glembek; Lukas Burget;
- // Saarland University
- // See ../../COPYING for clarification regarding multiple authors
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
- // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
- // MERCHANTABLITY OR NON-INFRINGEMENT.
- // See the Apache 2 License for the specific language governing permissions and
- // limitations under the License.
- #ifndef KALDI_BASE_KALDI_ERROR_H_
- #define KALDI_BASE_KALDI_ERROR_H_ 1
- #include <cstdio>
- #include <cstring>
- #include <sstream>
- #include <stdexcept>
- #include <string>
- #include <vector>
- #include "base/kaldi-types.h"
- #include "base/kaldi-utils.h"
- /* Important that this file does not depend on any other kaldi headers. */
- #ifdef _MSC_VER
- #define __func__ __FUNCTION__
- #endif
- namespace kaldi {
- /// \addtogroup error_group
- /// @{
- /***** PROGRAM NAME AND VERBOSITY LEVEL *****/
- /// Called by ParseOptions to set base name (no directory) of the executing
- /// program. The name is printed in logging code along with every message,
- /// because in our scripts, we often mix together the stderr of many programs.
- /// This function is very thread-unsafe.
- void SetProgramName(const char *basename);
- /// This is set by util/parse-options.{h,cc} if you set --verbose=? option.
- /// Do not use directly, prefer {Get,Set}VerboseLevel().
- extern int32 g_kaldi_verbose_level;
- /// Get verbosity level, usually set via command line '--verbose=' switch.
- inline int32 GetVerboseLevel() { return g_kaldi_verbose_level; }
- /// This should be rarely used, except by programs using Kaldi as library;
- /// command-line programs set the verbose level automatically from ParseOptions.
- inline void SetVerboseLevel(int32 i) { g_kaldi_verbose_level = i; }
- /***** KALDI LOGGING *****/
- /// Log message severity and source location info.
- struct LogMessageEnvelope {
- /// Message severity. In addition to these levels, positive values (1 to 6)
- /// specify verbose logging level. Verbose messages are produced only when
- /// SetVerboseLevel() has been called to set logging level to at least the
- /// corresponding value.
- enum Severity {
- kAssertFailed = -3, //!< Assertion failure. abort() will be called.
- kError = -2, //!< Fatal error. KaldiFatalError will be thrown.
- kWarning = -1, //!< Indicates a recoverable but abnormal condition.
- kInfo = 0, //!< Informational message.
- };
- int severity; //!< A Severity value, or positive verbosity level.
- const char *func; //!< Name of the function invoking the logging.
- const char *file; //!< Source file name with up to 1 leading directory.
- int32 line; //<! Line number in the source file.
- };
- /// Kaldi fatal runtime error exception. This exception is thrown from any use
- /// of the KALDI_ERR logging macro after the logging function, either set by
- /// SetLogHandler(), or the Kaldi's internal one, has returned.
- class KaldiFatalError : public std::runtime_error {
- public:
- explicit KaldiFatalError(const std::string &message)
- : std::runtime_error(message) {}
- explicit KaldiFatalError(const char *message) : std::runtime_error(message) {}
- /// Returns the exception name, "kaldi::KaldiFatalError".
- virtual const char *what() const noexcept override {
- return "kaldi::KaldiFatalError";
- }
- /// Returns the Kaldi error message logged by KALDI_ERR.
- const char *KaldiMessage() const { return std::runtime_error::what(); }
- };
- // Class MessageLogger is the workhorse behind the KALDI_ASSERT, KALDI_ERR,
- // KALDI_WARN, KALDI_LOG and KALDI_VLOG macros. It formats the message, then
- // either prints it to stderr or passes to the custom logging handler if
- // provided. Then, in case of the error, throws a KaldiFatalError exception, or
- // in case of failed KALDI_ASSERT, calls std::abort().
- class MessageLogger {
- public:
- /// The constructor stores the message's "envelope", a set of data which
- // identifies the location in source which is sending the message to log.
- // The pointers to strings are stored internally, and not owned or copied,
- // so that their storage must outlive this object.
- MessageLogger(LogMessageEnvelope::Severity severity, const char *func,
- const char *file, int32 line);
- // The stream insertion operator, used in e.g. 'KALDI_LOG << "Message"'.
- template <typename T> MessageLogger &operator<<(const T &val) {
- ss_ << val;
- return *this;
- }
- // When assigned a MessageLogger, log its contents.
- struct Log final {
- void operator=(const MessageLogger &logger) { logger.LogMessage(); }
- };
- // When assigned a MessageLogger, log its contents and then throw
- // a KaldiFatalError.
- struct LogAndThrow final {
- [[noreturn]] void operator=(const MessageLogger &logger) {
- logger.LogMessage();
- throw KaldiFatalError(logger.GetMessage());
- }
- };
- private:
- std::string GetMessage() const { return ss_.str(); }
- void LogMessage() const;
- LogMessageEnvelope envelope_;
- std::ostringstream ss_;
- };
- // Logging macros.
- #define KALDI_ERR \
- ::kaldi::MessageLogger::LogAndThrow() = ::kaldi::MessageLogger( \
- ::kaldi::LogMessageEnvelope::kError, __func__, __FILE__, __LINE__)
- #define KALDI_WARN \
- ::kaldi::MessageLogger::Log() = ::kaldi::MessageLogger( \
- ::kaldi::LogMessageEnvelope::kWarning, __func__, __FILE__, __LINE__)
- #define KALDI_LOG \
- ::kaldi::MessageLogger::Log() = ::kaldi::MessageLogger( \
- ::kaldi::LogMessageEnvelope::kInfo, __func__, __FILE__, __LINE__)
- #define KALDI_VLOG(v) \
- if ((v) <= ::kaldi::GetVerboseLevel()) \
- ::kaldi::MessageLogger::Log() = \
- ::kaldi::MessageLogger((::kaldi::LogMessageEnvelope::Severity)(v), \
- __func__, __FILE__, __LINE__)
- /***** KALDI ASSERTS *****/
- [[noreturn]] void KaldiAssertFailure_(const char *func, const char *file,
- int32 line, const char *cond_str);
- // Note on KALDI_ASSERT and KALDI_PARANOID_ASSERT:
- //
- // A single block {} around if /else does not work, because it causes
- // syntax error (unmatched else block) in the following code:
- //
- // if (condition)
- // KALDI_ASSERT(condition2);
- // else
- // SomethingElse();
- //
- // do {} while(0) -- note there is no semicolon at the end! -- works nicely,
- // and compilers will be able to optimize the loop away (as the condition
- // is always false).
- //
- // Also see KALDI_COMPILE_TIME_ASSERT, defined in base/kaldi-utils.h, and
- // KALDI_ASSERT_IS_INTEGER_TYPE and KALDI_ASSERT_IS_FLOATING_TYPE, also defined
- // there.
- #ifndef NDEBUG
- #define KALDI_ASSERT(cond) \
- do { \
- if (cond) \
- (void)0; \
- else \
- ::kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond); \
- } while (0)
- #else
- #define KALDI_ASSERT(cond) (void)0
- #endif
- // Some more expensive asserts only checked if this defined.
- #ifdef KALDI_PARANOID
- #define KALDI_PARANOID_ASSERT(cond) \
- do { \
- if (cond) \
- (void)0; \
- else \
- ::kaldi::KaldiAssertFailure_(__func__, __FILE__, __LINE__, #cond); \
- } while (0)
- #else
- #define KALDI_PARANOID_ASSERT(cond) (void)0
- #endif
- /***** THIRD-PARTY LOG-HANDLER *****/
- /// Type of third-party logging function.
- typedef void (*LogHandler)(const LogMessageEnvelope &envelope,
- const char *message);
- /// Set logging handler. If called with a non-NULL function pointer, the
- /// function pointed by it is called to send messages to a caller-provided log.
- /// If called with a NULL pointer, restores default Kaldi error logging to
- /// stderr. This function is obviously not thread safe; the log handler must be.
- /// Returns a previously set logging handler pointer, or NULL.
- LogHandler SetLogHandler(LogHandler);
- /// @} end "addtogroup error_group"
- //// Functions within internal is exported for testing only, do not use.
- //namespace internal {
- //bool LocateSymbolRange(const std::string &trace_name, size_t *begin,
- // size_t *end);
- //} // namespace internal
- } // namespace kaldi
- #endif // KALDI_BASE_KALDI_ERROR_H_
|