2f14625d828376d584655b3ba07d5cf754892f31
[supertux.git] / src / lisp / lisp.hpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #ifndef __LISPREADER_H__
21 #define __LISPREADER_H__
22
23 #include <string>
24 #include <vector>
25 #include <assert.h>
26
27 namespace lisp
28 {
29
30 class Lisp
31 {
32 public:
33   ~Lisp();
34     
35   enum LispType {
36     TYPE_CONS,
37     TYPE_SYMBOL,
38     TYPE_INTEGER,
39     TYPE_STRING,
40     TYPE_REAL,
41     TYPE_BOOLEAN
42   };
43
44   LispType get_type() const
45   { return type; } 
46
47   Lisp* get_car() const
48   { return v.cons.car; }
49   Lisp* get_cdr() const
50   { return v.cons.cdr; }
51   
52   bool get(std::string& val) const
53   { 
54     if(type != TYPE_STRING && type != TYPE_SYMBOL)
55       return false;
56     val = v.string;
57     return true;
58   }
59   
60   std::string get_string() const
61   {
62     assert(type == TYPE_STRING);
63     return v.string;
64   }
65   
66   bool get(unsigned int& val) const
67   {
68     if(type != TYPE_INTEGER)
69       return false;
70     val = v.integer;
71     return true;
72   }
73   
74   bool get(int& val) const
75   {
76     if(type != TYPE_INTEGER)
77       return false;
78     val = v.integer;
79     return true;
80   }
81
82   int get_int() const
83   {
84     assert(type == TYPE_INTEGER);
85     return v.integer;
86   }
87   
88   bool get(float& val) const
89   {
90     if(type != TYPE_REAL) {
91       if(type == TYPE_INTEGER) {
92         val = v.integer;
93         return true;
94       }
95       return false;
96     }
97     val = v.real;
98     return true;
99   }
100
101   float get_float() const
102   {
103     assert(type == TYPE_REAL);
104     return v.real;
105   }
106
107   bool get(bool& val) const
108   {
109     if(type != TYPE_BOOLEAN)
110       return false;
111     val = v.boolean;
112     return true;
113   }
114
115   bool get_bool() const
116   {
117     assert(type == TYPE_BOOLEAN);
118     return v.boolean;
119   }
120
121   /** conveniance functions which traverse the list until a child with a
122    * specified name is found. The value part is then interpreted in a specific
123    * way. The functions return true, if a child was found and could be
124    * interpreted correctly, otherwise false is returned and the variable value
125    * is not changed.
126    * (Please note that searching the lisp structure is O(n) so these functions
127    *  are no good idea for performance critical areas)
128    */
129   template<class T>
130   bool get(const char* name, T& val) const
131   {
132     const Lisp* lisp = get_lisp(name);
133     if(!lisp)
134       return false;
135
136     if(lisp->get_type() != TYPE_CONS)
137       return false;
138     lisp = lisp->get_car();
139     if(!lisp)
140       return false;
141     return lisp->get(val);
142   }
143
144   template<class T>
145   bool get_vector(const char* name, std::vector<T>& vec) const
146   {
147     vec.clear();
148     
149     const Lisp* child = get_lisp(name);
150     if(!child)
151       return false;
152     
153     for( ; child != 0; child = child->get_cdr()) {
154       T val;
155       if(!child->get_car())
156         continue;
157       if(child->get_car()->get(val)) {
158         vec.push_back(val);
159       }
160     }
161     
162     return true;
163   }
164   
165   Lisp* get_lisp(const char* name) const;
166   Lisp* get_lisp(const std::string& name) const
167   { return get_lisp(name.c_str()); }
168
169   // for debugging
170   void print(int indent = 0) const;
171
172 private:
173   friend class Parser;
174   Lisp(LispType newtype);
175
176   LispType type;
177   union
178   {
179     struct
180     {
181       Lisp* car;
182       Lisp* cdr;
183     } cons;
184
185     char* string;
186     int integer;
187     bool boolean;
188     float real;
189   } v;
190 };
191
192 } // end of namespace lisp
193
194 #endif
195