1 //  SuperTux
2 //  Copyright (C) 2015 Ingo Ruhnke <grumbel@gmail.com>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef HEADER_SUPERTUX_UTIL_READER_ERROR_HPP
18 #define HEADER_SUPERTUX_UTIL_READER_ERROR_HPP
19 
20 #include <sexp/value.hpp>
21 
22 #include <sstream>
23 #include <stdexcept>
24 #include <sexp/io.hpp>
25 
26 #include "util/reader_document.hpp"
27 
28 #define raise_exception(doc, sx, msg) raise_exception_real(__FILE__, __LINE__, doc, sx, msg)
29 
30 [[noreturn]]
31 inline void
raise_exception_real(const char * filename,int line,ReaderDocument const & doc,sexp::Value const & sx,const char * usermsg)32 raise_exception_real(const char* filename, int line,
33                      ReaderDocument const& doc, sexp::Value const& sx,
34                      const char* usermsg)
35 {
36   std::ostringstream msg;
37   msg << "[" << filename << ":" << line << "] "
38       << doc.get_filename() << ":" << sx.get_line() << ": "
39       << usermsg << " in expression:"
40       << "\n    " << sx;
41   throw std::runtime_error(msg.str());
42 }
43 
assert_is_boolean(ReaderDocument const & doc,sexp::Value const & sx)44 inline void assert_is_boolean(ReaderDocument const& doc, sexp::Value const& sx)
45 {
46   if (!sx.is_boolean())
47   {
48     raise_exception(doc, sx, "expected boolean");
49   }
50 }
51 
assert_is_integer(ReaderDocument const & doc,sexp::Value const & sx)52 inline void assert_is_integer(ReaderDocument const& doc, sexp::Value const& sx)
53 {
54   if (!sx.is_integer())
55   {
56     raise_exception(doc, sx, "expected integer");
57   }
58 }
59 
assert_is_real(ReaderDocument const & doc,sexp::Value const & sx)60 inline void assert_is_real(ReaderDocument const& doc, sexp::Value const& sx)
61 {
62   if (!sx.is_real())
63   {
64     raise_exception(doc, sx, "expected real");
65   }
66 }
67 
assert_is_symbol(ReaderDocument const & doc,sexp::Value const & sx)68 inline void assert_is_symbol(ReaderDocument const& doc, sexp::Value const& sx)
69 {
70   if (!sx.is_symbol())
71   {
72     raise_exception(doc, sx, "expected symbol");
73   }
74 }
75 
assert_is_string(ReaderDocument const & doc,sexp::Value const & sx)76 inline void assert_is_string(ReaderDocument const& doc, sexp::Value const& sx)
77 {
78   if (!sx.is_string())
79   {
80     raise_exception(doc, sx, "expected string");
81   }
82 }
83 
assert_is_array(ReaderDocument const & doc,sexp::Value const & sx)84 inline void assert_is_array(ReaderDocument const& doc, sexp::Value const& sx)
85 {
86   if (!sx.is_array())
87   {
88     raise_exception(doc, sx, "expected array");
89   }
90 }
91 
assert_array_size_ge(ReaderDocument const & doc,sexp::Value const & sx,int size)92 inline void assert_array_size_ge(ReaderDocument const& doc, sexp::Value const& sx, int size)
93 {
94   assert_is_array(doc, sx);
95 
96   if (!(static_cast<int>(sx.as_array().size()) >= size))
97   {
98     std::ostringstream msg;
99     msg << "array should contain " << size << " elements or more";
100     raise_exception(doc, sx, msg.str().c_str());
101   }
102 }
103 
assert_array_size_eq(ReaderDocument const & doc,sexp::Value const & sx,int size)104 inline void assert_array_size_eq(ReaderDocument const& doc, sexp::Value const& sx, int size)
105 {
106   assert_is_array(doc, sx);
107 
108   if (static_cast<int>(sx.as_array().size()) != size)
109   {
110     std::ostringstream msg;
111     msg << "array must have " << size << " elements, but has " << sx.as_array().size();
112     raise_exception(doc, sx, msg.str().c_str());
113   }
114 }
115 
116 #endif
117 
118 /* EOF */
119