Updated addon repository URL and improved debug output on download
[supertux.git] / src / lisp / lisp.hpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
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_LISP_LISP_HPP
18 #define HEADER_SUPERTUX_LISP_LISP_HPP
19
20 #include <assert.h>
21 #include <string>
22 #include <vector>
23
24 namespace lisp {
25
26 class Lisp
27 {
28 public:
29   ~Lisp();
30
31   enum LispType {
32     TYPE_CONS,
33     TYPE_SYMBOL,
34     TYPE_INTEGER,
35     TYPE_STRING,
36     TYPE_REAL,
37     TYPE_BOOLEAN
38   };
39
40   LispType get_type() const
41   { return type; }
42
43   const Lisp* get_car() const
44   { return v.cons.car; }
45   const Lisp* get_cdr() const
46   { return v.cons.cdr; }
47
48   bool get(std::string& val) const
49   {
50     if(type != TYPE_STRING && type != TYPE_SYMBOL)
51       return false;
52     val = v.string;
53     return true;
54   }
55
56   std::string get_symbol() const
57   {
58     assert(type == TYPE_SYMBOL);
59     return v.string;
60   }
61
62   std::string get_string() const
63   {
64     assert(type == TYPE_STRING);
65     return v.string;
66   }
67
68   bool get(unsigned int& val) const
69   {
70     if(type != TYPE_INTEGER)
71       return false;
72     val = v.integer;
73     return true;
74   }
75
76   bool get(int& val) const
77   {
78     if(type != TYPE_INTEGER)
79       return false;
80     val = v.integer;
81     return true;
82   }
83
84   int get_int() const
85   {
86     assert(type == TYPE_INTEGER);
87     return v.integer;
88   }
89
90   bool get(float& val) const
91   {
92     if(type != TYPE_REAL) {
93       if(type == TYPE_INTEGER) {
94         val = (float) v.integer;
95         return true;
96       }
97       return false;
98     }
99     val = v.real;
100     return true;
101   }
102
103   float get_float() const
104   {
105     assert(type == TYPE_REAL);
106     return v.real;
107   }
108
109   bool get(bool& val) const
110   {
111     if(type != TYPE_BOOLEAN)
112       return false;
113     val = v.boolean;
114     return true;
115   }
116
117   bool get_bool() const
118   {
119     assert(type == TYPE_BOOLEAN);
120     return v.boolean;
121   }
122
123   /** convenience functions which traverse the list until a child with a
124    * specified name is found. The value part is then interpreted in a specific
125    * way. The functions return true, if a child was found and could be
126    * interpreted correctly, otherwise false is returned and the variable value
127    * is not changed.
128    * (Please note that searching the lisp structure is O(n) so these functions
129    *  are not a good idea for performance critical areas)
130    */
131   template<class T>
132   bool get(const char* name, T& val) const
133   {
134     const Lisp* lisp = get_lisp(name);
135     if(!lisp)
136       return false;
137
138     if(lisp->get_type() != TYPE_CONS)
139       return false;
140     lisp = lisp->get_car();
141     if(!lisp)
142       return false;
143     return lisp->get(val);
144   }
145
146   template<class T>
147   bool get(const char* name, std::vector<T>& vec) const
148   {
149     vec.clear();
150
151     const Lisp* child = get_lisp(name);
152     if(!child)
153       return false;
154
155     for( ; child != 0; child = child->get_cdr()) {
156       T val;
157       if(!child->get_car())
158         continue;
159       if(child->get_car()->get(val)) {
160         vec.push_back(val);
161       }
162     }
163
164     return true;
165   }
166
167   const Lisp* get_lisp(const char* name) const;
168   const Lisp* get_lisp(const std::string& name) const
169   { return get_lisp(name.c_str()); }
170
171   // for debugging
172   void print(int indent = 0) const;
173
174 private:
175   friend class Parser;
176   Lisp(LispType newtype);
177
178   LispType type;
179   union
180   {
181     struct
182     {
183       const Lisp* car;
184       const Lisp* cdr;
185     } cons;
186
187     char* string;
188     int integer;
189     bool boolean;
190     float real;
191   } v;
192 };
193
194 } // end of namespace lisp
195
196 #endif
197
198 /* EOF */