exceptions.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. #ifndef EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
  2. #define EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
  3. #if defined(_MSC_VER) || \
  4. (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
  5. (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
  6. #pragma once
  7. #endif
  8. #include "yaml-cpp/mark.h"
  9. #include "yaml-cpp/noexcept.h"
  10. #include "yaml-cpp/traits.h"
  11. #include <sstream>
  12. #include <stdexcept>
  13. #include <string>
  14. namespace YAML {
  15. // error messages
  16. namespace ErrorMsg {
  17. const char* const YAML_DIRECTIVE_ARGS =
  18. "YAML directives must have exactly one argument";
  19. const char* const YAML_VERSION = "bad YAML version: ";
  20. const char* const YAML_MAJOR_VERSION = "YAML major version too large";
  21. const char* const REPEATED_YAML_DIRECTIVE = "repeated YAML directive";
  22. const char* const TAG_DIRECTIVE_ARGS =
  23. "TAG directives must have exactly two arguments";
  24. const char* const REPEATED_TAG_DIRECTIVE = "repeated TAG directive";
  25. const char* const CHAR_IN_TAG_HANDLE =
  26. "illegal character found while scanning tag handle";
  27. const char* const TAG_WITH_NO_SUFFIX = "tag handle with no suffix";
  28. const char* const END_OF_VERBATIM_TAG = "end of verbatim tag not found";
  29. const char* const END_OF_MAP = "end of map not found";
  30. const char* const END_OF_MAP_FLOW = "end of map flow not found";
  31. const char* const END_OF_SEQ = "end of sequence not found";
  32. const char* const END_OF_SEQ_FLOW = "end of sequence flow not found";
  33. const char* const MULTIPLE_TAGS =
  34. "cannot assign multiple tags to the same node";
  35. const char* const MULTIPLE_ANCHORS =
  36. "cannot assign multiple anchors to the same node";
  37. const char* const MULTIPLE_ALIASES =
  38. "cannot assign multiple aliases to the same node";
  39. const char* const ALIAS_CONTENT =
  40. "aliases can't have any content, *including* tags";
  41. const char* const INVALID_HEX = "bad character found while scanning hex number";
  42. const char* const INVALID_UNICODE = "invalid unicode: ";
  43. const char* const INVALID_ESCAPE = "unknown escape character: ";
  44. const char* const UNKNOWN_TOKEN = "unknown token";
  45. const char* const DOC_IN_SCALAR = "illegal document indicator in scalar";
  46. const char* const EOF_IN_SCALAR = "illegal EOF in scalar";
  47. const char* const CHAR_IN_SCALAR = "illegal character in scalar";
  48. const char* const TAB_IN_INDENTATION =
  49. "illegal tab when looking for indentation";
  50. const char* const FLOW_END = "illegal flow end";
  51. const char* const BLOCK_ENTRY = "illegal block entry";
  52. const char* const MAP_KEY = "illegal map key";
  53. const char* const MAP_VALUE = "illegal map value";
  54. const char* const ALIAS_NOT_FOUND = "alias not found after *";
  55. const char* const ANCHOR_NOT_FOUND = "anchor not found after &";
  56. const char* const CHAR_IN_ALIAS =
  57. "illegal character found while scanning alias";
  58. const char* const CHAR_IN_ANCHOR =
  59. "illegal character found while scanning anchor";
  60. const char* const ZERO_INDENT_IN_BLOCK =
  61. "cannot set zero indentation for a block scalar";
  62. const char* const CHAR_IN_BLOCK = "unexpected character in block scalar";
  63. const char* const AMBIGUOUS_ANCHOR =
  64. "cannot assign the same alias to multiple nodes";
  65. const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined";
  66. const char* const INVALID_NODE =
  67. "invalid node; this may result from using a map iterator as a sequence "
  68. "iterator, or vice-versa";
  69. const char* const INVALID_SCALAR = "invalid scalar";
  70. const char* const KEY_NOT_FOUND = "key not found";
  71. const char* const BAD_CONVERSION = "bad conversion";
  72. const char* const BAD_DEREFERENCE = "bad dereference";
  73. const char* const BAD_SUBSCRIPT = "operator[] call on a scalar";
  74. const char* const BAD_PUSHBACK = "appending to a non-sequence";
  75. const char* const BAD_INSERT = "inserting in a non-convertible-to-map";
  76. const char* const UNMATCHED_GROUP_TAG = "unmatched group tag";
  77. const char* const UNEXPECTED_END_SEQ = "unexpected end sequence token";
  78. const char* const UNEXPECTED_END_MAP = "unexpected end map token";
  79. const char* const SINGLE_QUOTED_CHAR =
  80. "invalid character in single-quoted string";
  81. const char* const INVALID_ANCHOR = "invalid anchor";
  82. const char* const INVALID_ALIAS = "invalid alias";
  83. const char* const INVALID_TAG = "invalid tag";
  84. const char* const BAD_FILE = "bad file";
  85. template <typename T>
  86. inline const std::string KEY_NOT_FOUND_WITH_KEY(
  87. const T&, typename disable_if<is_numeric<T>>::type* = 0) {
  88. return KEY_NOT_FOUND;
  89. }
  90. inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
  91. std::stringstream stream;
  92. stream << KEY_NOT_FOUND << ": " << key;
  93. return stream.str();
  94. }
  95. inline const std::string KEY_NOT_FOUND_WITH_KEY(const char* key) {
  96. std::stringstream stream;
  97. stream << KEY_NOT_FOUND << ": " << key;
  98. return stream.str();
  99. }
  100. template <typename T>
  101. inline const std::string KEY_NOT_FOUND_WITH_KEY(
  102. const T& key, typename enable_if<is_numeric<T>>::type* = 0) {
  103. std::stringstream stream;
  104. stream << KEY_NOT_FOUND << ": " << key;
  105. return stream.str();
  106. }
  107. template <typename T>
  108. inline const std::string BAD_SUBSCRIPT_WITH_KEY(
  109. const T&, typename disable_if<is_numeric<T>>::type* = nullptr) {
  110. return BAD_SUBSCRIPT;
  111. }
  112. inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& key) {
  113. std::stringstream stream;
  114. stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
  115. return stream.str();
  116. }
  117. inline const std::string BAD_SUBSCRIPT_WITH_KEY(const char* key) {
  118. std::stringstream stream;
  119. stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
  120. return stream.str();
  121. }
  122. template <typename T>
  123. inline const std::string BAD_SUBSCRIPT_WITH_KEY(
  124. const T& key, typename enable_if<is_numeric<T>>::type* = nullptr) {
  125. std::stringstream stream;
  126. stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
  127. return stream.str();
  128. }
  129. inline const std::string INVALID_NODE_WITH_KEY(const std::string& key) {
  130. std::stringstream stream;
  131. if (key.empty()) {
  132. return INVALID_NODE;
  133. }
  134. stream << "invalid node; first invalid key: \"" << key << "\"";
  135. return stream.str();
  136. }
  137. } // namespace ErrorMsg
  138. class YAML_CPP_API Exception : public std::runtime_error {
  139. public:
  140. Exception(const Mark& mark_, const std::string& msg_)
  141. : std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
  142. ~Exception() YAML_CPP_NOEXCEPT override;
  143. Exception(const Exception&) = default;
  144. Mark mark;
  145. std::string msg;
  146. private:
  147. static const std::string build_what(const Mark& mark,
  148. const std::string& msg) {
  149. if (mark.is_null()) {
  150. return msg;
  151. }
  152. std::stringstream output;
  153. output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
  154. << mark.column + 1 << ": " << msg;
  155. return output.str();
  156. }
  157. };
  158. class YAML_CPP_API ParserException : public Exception {
  159. public:
  160. ParserException(const Mark& mark_, const std::string& msg_)
  161. : Exception(mark_, msg_) {}
  162. ParserException(const ParserException&) = default;
  163. ~ParserException() YAML_CPP_NOEXCEPT override;
  164. };
  165. class YAML_CPP_API RepresentationException : public Exception {
  166. public:
  167. RepresentationException(const Mark& mark_, const std::string& msg_)
  168. : Exception(mark_, msg_) {}
  169. RepresentationException(const RepresentationException&) = default;
  170. ~RepresentationException() YAML_CPP_NOEXCEPT override;
  171. };
  172. // representation exceptions
  173. class YAML_CPP_API InvalidScalar : public RepresentationException {
  174. public:
  175. InvalidScalar(const Mark& mark_)
  176. : RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
  177. InvalidScalar(const InvalidScalar&) = default;
  178. ~InvalidScalar() YAML_CPP_NOEXCEPT override;
  179. };
  180. class YAML_CPP_API KeyNotFound : public RepresentationException {
  181. public:
  182. template <typename T>
  183. KeyNotFound(const Mark& mark_, const T& key_)
  184. : RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
  185. }
  186. KeyNotFound(const KeyNotFound&) = default;
  187. ~KeyNotFound() YAML_CPP_NOEXCEPT override;
  188. };
  189. template <typename T>
  190. class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
  191. public:
  192. TypedKeyNotFound(const Mark& mark_, const T& key_)
  193. : KeyNotFound(mark_, key_), key(key_) {}
  194. ~TypedKeyNotFound() YAML_CPP_NOEXCEPT override = default;
  195. T key;
  196. };
  197. template <typename T>
  198. inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
  199. const T& key) {
  200. return TypedKeyNotFound<T>(mark, key);
  201. }
  202. class YAML_CPP_API InvalidNode : public RepresentationException {
  203. public:
  204. InvalidNode(const std::string& key)
  205. : RepresentationException(Mark::null_mark(),
  206. ErrorMsg::INVALID_NODE_WITH_KEY(key)) {}
  207. InvalidNode(const InvalidNode&) = default;
  208. ~InvalidNode() YAML_CPP_NOEXCEPT override;
  209. };
  210. class YAML_CPP_API BadConversion : public RepresentationException {
  211. public:
  212. explicit BadConversion(const Mark& mark_)
  213. : RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
  214. BadConversion(const BadConversion&) = default;
  215. ~BadConversion() YAML_CPP_NOEXCEPT override;
  216. };
  217. template <typename T>
  218. class TypedBadConversion : public BadConversion {
  219. public:
  220. explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
  221. };
  222. class YAML_CPP_API BadDereference : public RepresentationException {
  223. public:
  224. BadDereference()
  225. : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
  226. BadDereference(const BadDereference&) = default;
  227. ~BadDereference() YAML_CPP_NOEXCEPT override;
  228. };
  229. class YAML_CPP_API BadSubscript : public RepresentationException {
  230. public:
  231. template <typename Key>
  232. BadSubscript(const Mark& mark_, const Key& key)
  233. : RepresentationException(mark_, ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
  234. BadSubscript(const BadSubscript&) = default;
  235. ~BadSubscript() YAML_CPP_NOEXCEPT override;
  236. };
  237. class YAML_CPP_API BadPushback : public RepresentationException {
  238. public:
  239. BadPushback()
  240. : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
  241. BadPushback(const BadPushback&) = default;
  242. ~BadPushback() YAML_CPP_NOEXCEPT override;
  243. };
  244. class YAML_CPP_API BadInsert : public RepresentationException {
  245. public:
  246. BadInsert()
  247. : RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
  248. BadInsert(const BadInsert&) = default;
  249. ~BadInsert() YAML_CPP_NOEXCEPT override;
  250. };
  251. class YAML_CPP_API EmitterException : public Exception {
  252. public:
  253. EmitterException(const std::string& msg_)
  254. : Exception(Mark::null_mark(), msg_) {}
  255. EmitterException(const EmitterException&) = default;
  256. ~EmitterException() YAML_CPP_NOEXCEPT override;
  257. };
  258. class YAML_CPP_API BadFile : public Exception {
  259. public:
  260. explicit BadFile(const std::string& filename)
  261. : Exception(Mark::null_mark(),
  262. std::string(ErrorMsg::BAD_FILE) + ": " + filename) {}
  263. BadFile(const BadFile&) = default;
  264. ~BadFile() YAML_CPP_NOEXCEPT override;
  265. };
  266. } // namespace YAML
  267. #endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66