1 #ifndef MARISA_EXCEPTION_H_
2 #define MARISA_EXCEPTION_H_
3 
4 #include <exception>
5 
6 #include "marisa/base.h"
7 
8 namespace marisa {
9 
10 // An exception object keeps a filename, a line number, an error code and an
11 // error message. The message format is as follows:
12 //  "__FILE__:__LINE__: error_code: error_message"
13 class Exception : public std::exception {
14  public:
Exception(const char * filename,int line,ErrorCode error_code,const char * error_message)15   Exception(const char *filename, int line,
16       ErrorCode error_code, const char *error_message)
17       : std::exception(), filename_(filename), line_(line),
18         error_code_(error_code), error_message_(error_message) {}
Exception(const Exception & ex)19   Exception(const Exception &ex)
20       : std::exception(), filename_(ex.filename_), line_(ex.line_),
21         error_code_(ex.error_code_), error_message_(ex.error_message_) {}
~Exception()22   virtual ~Exception() throw() {}
23 
24   Exception &operator=(const Exception &rhs) {
25     filename_ = rhs.filename_;
26     line_ = rhs.line_;
27     error_code_ = rhs.error_code_;
28     error_message_ = rhs.error_message_;
29     return *this;
30   }
31 
filename()32   const char *filename() const {
33     return filename_;
34   }
line()35   int line() const {
36     return line_;
37   }
error_code()38   ErrorCode error_code() const {
39     return error_code_;
40   }
error_message()41   const char *error_message() const {
42     return error_message_;
43   }
44 
what()45   virtual const char *what() const throw() {
46     return error_message_;
47   }
48 
49  private:
50   const char *filename_;
51   int line_;
52   ErrorCode error_code_;
53   const char *error_message_;
54 };
55 
56 // These macros are used to convert a line number to a string constant.
57 #define MARISA_INT_TO_STR(value) #value
58 #define MARISA_LINE_TO_STR(line) MARISA_INT_TO_STR(line)
59 #define MARISA_LINE_STR MARISA_LINE_TO_STR(__LINE__)
60 
61 // MARISA_THROW throws an exception with a filename, a line number, an error
62 // code and an error message. The message format is as follows:
63 //  "__FILE__:__LINE__: error_code: error_message"
64 #define MARISA_THROW(error_code, error_message) \
65   (throw marisa::Exception(__FILE__, __LINE__, error_code, \
66        __FILE__ ":" MARISA_LINE_STR ": " #error_code ": " error_message))
67 
68 // MARISA_THROW_IF throws an exception if `condition' is true.
69 #define MARISA_THROW_IF(condition, error_code) \
70   (void)((!(condition)) || (MARISA_THROW(error_code, #condition), 0))
71 
72 // MARISA_DEBUG_IF is ignored if _DEBUG is undefined. So, it is useful for
73 // debugging time-critical codes.
74 #ifdef _DEBUG
75  #define MARISA_DEBUG_IF(cond, error_code) MARISA_THROW_IF(cond, error_code)
76 #else
77  #define MARISA_DEBUG_IF(cond, error_code)
78 #endif
79 
80 }  // namespace marisa
81 
82 #endif  // MARISA_EXCEPTION_H_
83